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.

782 lines
21 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999-2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * Output.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Classes to output a span for a particular brush type
  12. *
  13. * Created:
  14. *
  15. * 2/24/1999 DCurtis
  16. *
  17. \**************************************************************************/
  18. #ifndef _OUTPUT_HPP
  19. #define _OUTPUT_HPP
  20. void ApplyWrapMode(INT WrapMode, INT &x, INT &y, INT w, INT h);
  21. //--------------------------------------------------------------------------
  22. // Solid color output
  23. //--------------------------------------------------------------------------
  24. class DpOutputSolidColorSpan : public DpOutputSpan
  25. {
  26. public:
  27. ARGB Argb;
  28. DpScanBuffer * Scan;
  29. public:
  30. DpOutputSolidColorSpan(ARGB argb, DpScanBuffer * scan)
  31. {
  32. Argb = argb;
  33. Scan = scan;
  34. }
  35. GpStatus OutputSpan(
  36. INT y,
  37. INT xMin,
  38. INT xMax
  39. );
  40. virtual BOOL IsValid() const { return TRUE; }
  41. virtual DpScanBuffer* GetScanBuffer(){ return Scan; }
  42. };
  43. //--------------------------------------------------------------------------
  44. // Gradient output base class
  45. //--------------------------------------------------------------------------
  46. class DpOutputGradientSpan : public DpOutputSpan
  47. {
  48. private:
  49. // We now use an ObjectTag to determine if the object is valid
  50. // instead of using a BOOL. This is much more robust and helps
  51. // with debugging. It also enables us to version our objects
  52. // more easily with a version number in the ObjectTag.
  53. ObjectTag Tag; // Keep this as the 1st value in the object!
  54. protected:
  55. VOID SetValid(BOOL valid)
  56. {
  57. Tag = valid ? ObjectTagOutputGradientSpan : ObjectTagInvalid;
  58. }
  59. public:
  60. virtual BOOL IsValid() const
  61. {
  62. ASSERT((Tag == ObjectTagOutputGradientSpan) || (Tag == ObjectTagInvalid));
  63. #if DBG
  64. if (Tag == ObjectTagInvalid)
  65. {
  66. WARNING1("Invalid OutputGradientSpan");
  67. }
  68. #endif
  69. return (Tag == ObjectTagOutputGradientSpan);
  70. }
  71. public:
  72. DpScanBuffer * Scan;
  73. const GpBrush* Brush;
  74. INT BrushType;
  75. INT WrapMode;
  76. INT CompositingMode;
  77. GpRectF BrushRect;
  78. GpMatrix WorldToDevice;
  79. GpMatrix DeviceToWorld;
  80. REAL A[4], R[4], G[4], B[4];
  81. public:
  82. DpOutputGradientSpan() { SetValid (TRUE); }
  83. DpOutputGradientSpan(
  84. const GpElementaryBrush *brush,
  85. DpScanBuffer * scan,
  86. DpContext* context
  87. );
  88. ~DpOutputGradientSpan()
  89. {
  90. SetValid(FALSE); // so we don't use a deleted object
  91. }
  92. virtual GpStatus OutputSpan(
  93. INT y,
  94. INT xMin,
  95. INT xMax
  96. );
  97. DpScanBuffer* GetScanBuffer(){ return Scan; }
  98. protected:
  99. VOID InitDefaultColorArrays(const GpElementaryBrush* brush)
  100. {
  101. const GpGradientBrush *gradBrush
  102. = static_cast<const GpGradientBrush*> (brush);
  103. if(gradBrush->UsesDefaultColorArray())
  104. {
  105. GpColor colors[4]; // Default array is up to
  106. // 4 colors.
  107. gradBrush->GetColors(colors);
  108. INT num = gradBrush->GetNumberOfColors();
  109. for(INT i = 0; i < num; i++)
  110. {
  111. ARGB argb = colors[i].GetPremultipliedValue();
  112. A[i] = (REAL)GpColor::GetAlphaARGB(argb);
  113. R[i] = (REAL)GpColor::GetRedARGB(argb);
  114. G[i] = (REAL)GpColor::GetGreenARGB(argb);
  115. B[i] = (REAL)GpColor::GetBlueARGB(argb);
  116. }
  117. }
  118. }
  119. };
  120. //--------------------------------------------------------------------------
  121. // Handle one-dimension gradients (we call 'em 'textures' for reasons that
  122. // should be obvious)
  123. //--------------------------------------------------------------------------
  124. class DpOutputOneDGradientSpan : public DpOutputGradientSpan
  125. {
  126. protected:
  127. INT OneDDataMultiplier;
  128. INT OneDDataCount;
  129. ARGB* OneDData;
  130. BOOL IsHorizontal;
  131. BOOL IsVertical;
  132. public:
  133. DpOutputOneDGradientSpan()
  134. {
  135. Initialize();
  136. }
  137. DpOutputOneDGradientSpan(
  138. const GpElementaryBrush *brush,
  139. DpScanBuffer *scan,
  140. DpContext *context,
  141. BOOL isHorizontal = TRUE,
  142. BOOL isVertical = FALSE
  143. );
  144. ~DpOutputOneDGradientSpan();
  145. virtual GpStatus OutputSpan(
  146. INT y,
  147. INT xMin,
  148. INT xMax
  149. );
  150. protected:
  151. VOID Initialize()
  152. {
  153. OneDDataMultiplier = 1;
  154. OneDDataCount = 0;
  155. OneDData = NULL;
  156. IsHorizontal = FALSE;
  157. IsVertical = FALSE;
  158. SetValid(FALSE);
  159. }
  160. GpStatus AllocateOneDData(BOOL isHorizontal,BOOL isVertical);
  161. VOID SetupRectGradientOneDData();
  162. VOID SetupRadialGradientOneDData();
  163. };
  164. //--------------------------------------------------------------------------
  165. // Linear gradients
  166. //--------------------------------------------------------------------------
  167. // The AGRB64TEXEL structure is sort of funky in order to optimize the
  168. // inner loop of our C-code linear gradient routine.
  169. struct AGRB64TEXEL // Note that it's 'AGRB', not 'ARGB'
  170. {
  171. UINT32 A00rr00bb; // Texel's R and B components
  172. UINT32 A00aa00gg; // Texel's A and G components
  173. };
  174. // # of pixels in our 1-D texture:
  175. //#define ONEDMAXIMUMTEXELS 32
  176. #define ONEDMAXIMUMTEXELS 1024
  177. // # of fractional bits that we iterate across the texture with:
  178. #define ONEDNUMFRACTIONALBITS 16
  179. // Get the integer portion of our fixed point texture coordinate, using
  180. // a floor function:
  181. #define ONEDGETINTEGERBITS(x) ((x) >> ONEDNUMFRACTIONALBITS)
  182. // Get the 8-bit fractional portion of our fixed point texture coordinate.
  183. // We could round, but I can't be bothered:
  184. #define ONEDGETFRACTIONAL8BITS(x) ((x) >> ((ONEDNUMFRACTIONALBITS - 8)) & 0xff)
  185. class DpOutputLinearGradientSpan : public DpOutputGradientSpan
  186. {
  187. protected:
  188. GpMatrix DeviceToNormalized; // Transforms from the device-space brush
  189. // parallogram to fixed-point-scaled
  190. // brush texture coordinates
  191. INT32 M11; // Fixed point representation of
  192. // M11 element of DeviceToNormalized
  193. INT32 M21; // Fixed point representation of
  194. // M21 element of DeviceToNormalized
  195. INT32 Dx; // Fixed point representation of
  196. // Dx element of DeviceToNormalized
  197. INT32 XIncrement; // Fixed point increment (in format
  198. // defined by ONEDNUMFRACTIONALBITS)
  199. // representing texture x-distance
  200. // traveled for every x pixel increment
  201. // in device space
  202. UINT32 IntervalMask; // One less than the number of texels in
  203. // our texture
  204. UINT32 NumberOfIntervalBits; // log2 of the number of texels
  205. union
  206. {
  207. ULONGLONG StartTexelArgb[ONEDMAXIMUMTEXELS];
  208. // Array of colors (at 16-bits per channel,
  209. // with zeroes in the significant bytes)
  210. // representing the start color of the
  211. // linear approximation at interval 'x'
  212. // (in A-R-G-B format)
  213. AGRB64TEXEL StartTexelAgrb[ONEDMAXIMUMTEXELS];
  214. // Similarly, but for the non-MMX renderer
  215. // (in A-G-R-B format)
  216. };
  217. union
  218. {
  219. ULONGLONG EndTexelArgb[ONEDMAXIMUMTEXELS];
  220. // End color for the interval (in A-R-G-B
  221. // format)
  222. AGRB64TEXEL EndTexelAgrb[ONEDMAXIMUMTEXELS];
  223. // Similarly, but for the non-MMX renderer
  224. // (in A-G-R-B format)
  225. };
  226. public:
  227. DpOutputLinearGradientSpan(
  228. const GpElementaryBrush *brush,
  229. DpScanBuffer *scan,
  230. DpContext *context
  231. );
  232. virtual GpStatus OutputSpan(
  233. INT y,
  234. INT xMin,
  235. INT xMax
  236. );
  237. };
  238. //--------------------------------------------------------------------------
  239. // Gradient special case - MMX
  240. //--------------------------------------------------------------------------
  241. class DpOutputLinearGradientSpan_MMX : public DpOutputLinearGradientSpan
  242. {
  243. public:
  244. DpOutputLinearGradientSpan_MMX(
  245. const GpElementaryBrush *brush,
  246. DpScanBuffer *scan,
  247. DpContext *context
  248. );
  249. virtual GpStatus OutputSpan(
  250. INT y,
  251. INT xMin,
  252. INT xMax
  253. );
  254. };
  255. //--------------------------------------------------------------------------
  256. // Path gradients
  257. //--------------------------------------------------------------------------
  258. class DpOutputOneDPathGradientSpan : public DpOutputOneDGradientSpan
  259. {
  260. public:
  261. DpOutputOneDPathGradientSpan()
  262. {
  263. BLTransforms = NULL;
  264. Count = 0;
  265. }
  266. ~DpOutputOneDPathGradientSpan()
  267. {
  268. if(BLTransforms)
  269. delete[] BLTransforms;
  270. }
  271. DpOutputOneDPathGradientSpan(
  272. const GpElementaryBrush *brush,
  273. DpScanBuffer * scan,
  274. DpContext* context,
  275. BOOL isHorizontal = TRUE,
  276. BOOL isVertical = FALSE
  277. );
  278. virtual GpStatus OutputSpan(
  279. INT y,
  280. INT xMin,
  281. INT xMax
  282. );
  283. protected:
  284. VOID SetupPathGradientOneDData(BOOL gammaCorrect);
  285. protected:
  286. GpBilinearTransform* BLTransforms;
  287. INT Count;
  288. };
  289. class DpTriangleData
  290. {
  291. friend class DpOutputTriangleGradientSpan;
  292. friend class DpOutputPathGradientSpan;
  293. private:
  294. // We now use an ObjectTag to determine if the object is valid
  295. // instead of using a BOOL. This is much more robust and helps
  296. // with debugging. It also enables us to version our objects
  297. // more easily with a version number in the ObjectTag.
  298. ObjectTag Tag; // Keep this as the 1st value in the object!
  299. protected:
  300. VOID SetValid(BOOL valid)
  301. {
  302. Tag = valid ? ObjectTagTriangleData : ObjectTagInvalid;
  303. }
  304. virtual BOOL IsValid() const
  305. {
  306. ASSERT((Tag == ObjectTagTriangleData) || (Tag == ObjectTagInvalid));
  307. #if DBG
  308. if (Tag == ObjectTagInvalid)
  309. {
  310. WARNING1("Invalid TriangleData");
  311. }
  312. #endif
  313. return (Tag == ObjectTagTriangleData);
  314. }
  315. public:
  316. DpTriangleData();
  317. ~DpTriangleData()
  318. {
  319. SetValid(FALSE); // so we don't use a deleted object
  320. }
  321. VOID SetTriangle(
  322. GpPointF& pt0,
  323. GpPointF& pt1,
  324. GpPointF& pt2,
  325. GpColor& color0,
  326. GpColor& color1,
  327. GpColor& color2,
  328. BOOL isPolygonMode = FALSE,
  329. BOOL isGammaCorrected = FALSE
  330. );
  331. GpStatus OutputSpan(ARGB* buffer, INT compositingMode,
  332. INT y, INT &xMin, INT &xMax);
  333. private:
  334. BOOL GetXSpan(REAL y, REAL xmin, REAL xmax, REAL* x, GpPointF* s);
  335. BOOL SetXSpan(REAL y, REAL xmin, REAL xmax, REAL* x);
  336. private:
  337. BOOL IsPolygonMode;
  338. BOOL GammaCorrect;
  339. INT Index[3];
  340. REAL X[3];
  341. REAL Y[3];
  342. GpFColor128 Color[3];
  343. REAL Falloff0;
  344. REAL Falloff1;
  345. REAL Falloff2;
  346. INT BlendCount0;
  347. INT BlendCount1;
  348. INT BlendCount2;
  349. REAL* BlendFactors0;
  350. REAL* BlendFactors1;
  351. REAL* BlendFactors2;
  352. REAL* BlendPositions0;
  353. REAL* BlendPositions1;
  354. REAL* BlendPositions2;
  355. ARGB* PresetColors;
  356. BOOL UsesPresetColors;
  357. REAL Xmin, Xmax;
  358. REAL M[3]; // dx/dy
  359. REAL DeltaY[3]; // Inverse of dy.
  360. PointF STGradient[2]; // Cached starting and ending fractional values of
  361. // the color gradients for the current XSpan
  362. REAL XSpan[2]; // Cached X range covered by this triangle for
  363. // the current value of Y being output
  364. };
  365. //--------------------------------------------------------------------------
  366. // Triangle Gradients
  367. //--------------------------------------------------------------------------
  368. class DpOutputTriangleGradientSpan : public DpOutputGradientSpan
  369. {
  370. public:
  371. DpOutputTriangleGradientSpan() {}
  372. DpOutputTriangleGradientSpan(
  373. const GpElementaryBrush *brush,
  374. DpScanBuffer * scan,
  375. DpContext* context
  376. );
  377. virtual GpStatus OutputSpan(
  378. INT y,
  379. INT xMin,
  380. INT xMax
  381. );
  382. DpScanBuffer* GetScanBuffer(){ return Scan; }
  383. private:
  384. DpTriangleData Triangle;
  385. };
  386. //--------------------------------------------------------------------------
  387. // Path Gradients
  388. //--------------------------------------------------------------------------
  389. class DpOutputPathGradientSpan : public DpOutputGradientSpan
  390. {
  391. public:
  392. INT Count;
  393. DpTriangleData** Triangles;
  394. public:
  395. DpOutputPathGradientSpan()
  396. {
  397. Count = 0;
  398. Triangles = NULL;
  399. SetValid(FALSE);
  400. }
  401. DpOutputPathGradientSpan(
  402. const GpElementaryBrush *brush,
  403. DpScanBuffer * scan,
  404. DpContext* context
  405. );
  406. virtual ~DpOutputPathGradientSpan();
  407. virtual GpStatus OutputSpan(
  408. INT y,
  409. INT xMin,
  410. INT xMax
  411. );
  412. DpScanBuffer* GetScanBuffer(){ return Scan; }
  413. protected:
  414. VOID FreeData();
  415. };
  416. //--------------------------------------------------------------------------
  417. // Textures
  418. //--------------------------------------------------------------------------
  419. class DpOutputBilinearSpan : public DpOutputSpan
  420. {
  421. protected:
  422. const GpBitmap *Bitmap;
  423. const DpBitmap *dBitmap;
  424. BitmapData BmpData;
  425. DpScanBuffer *Scan;
  426. WrapMode BilinearWrapMode;
  427. ARGB ClampColor;
  428. BOOL SrcRectClamp;
  429. GpRectF SrcRect;
  430. GpMatrix WorldToDevice;
  431. GpMatrix DeviceToWorld;
  432. public:
  433. DpOutputBilinearSpan(
  434. const GpTexture *textureBrush,
  435. DpScanBuffer *scan,
  436. GpMatrix *worldToDevice,
  437. DpContext *context
  438. );
  439. DpOutputBilinearSpan(
  440. const DpBitmap *bitmap,
  441. DpScanBuffer *scan,
  442. GpMatrix *worldToDevice,
  443. DpContext *context,
  444. DpImageAttributes *imageAttributes
  445. );
  446. DpOutputBilinearSpan(
  447. DpBitmap* bitmap,
  448. DpScanBuffer * scan,
  449. DpContext* context,
  450. DpImageAttributes imageAttributes,
  451. INT numPoints,
  452. const GpPointF *dstPoints,
  453. const GpRectF *srcRect
  454. );
  455. virtual ~DpOutputBilinearSpan();
  456. virtual GpStatus OutputSpan(
  457. INT y,
  458. INT xMin,
  459. INT xMax
  460. );
  461. virtual BOOL IsValid() const
  462. {
  463. return ((dBitmap != NULL) || (Bitmap != NULL));
  464. }
  465. DpScanBuffer* GetScanBuffer()
  466. {
  467. return Scan;
  468. }
  469. };
  470. //--------------------------------------------------------------------------
  471. // Textures - MMX
  472. //
  473. // The MMX code uses the same setup as the non-MMX, hence the reason
  474. // we're derived from it.
  475. //--------------------------------------------------------------------------
  476. class DpOutputBilinearSpan_MMX : public DpOutputBilinearSpan
  477. {
  478. protected:
  479. BOOL TranslateMatrixValid; // TRUE if Dx, and Dy are valid
  480. BOOL ScaleMatrixValid; // TRUE if M11-M22 are valid
  481. INT M11; // 16.16 fixed point representation of the
  482. INT M12; // device-to-world transform
  483. INT M21;
  484. INT M22;
  485. INT Dx;
  486. INT Dy;
  487. INT UIncrement; // Increment in texture space for every one-
  488. INT VIncrement; // pixel-to-the-right in device space
  489. INT ModulusWidth; // Modulus value for doing tiling
  490. INT ModulusHeight;
  491. INT XEdgeIncrement; // Edge condition increments.
  492. INT YEdgeIncrement;
  493. public:
  494. VOID InitializeFixedPointState();
  495. DpOutputBilinearSpan_MMX(
  496. const GpTexture *textureBrush,
  497. DpScanBuffer *scan,
  498. GpMatrix *worldToDevice,
  499. DpContext *context
  500. ) : DpOutputBilinearSpan(textureBrush, scan, worldToDevice, context)
  501. {
  502. InitializeFixedPointState();
  503. }
  504. DpOutputBilinearSpan_MMX(
  505. const DpBitmap *bitmap,
  506. DpScanBuffer *scan,
  507. GpMatrix *worldToDevice,
  508. DpContext *context,
  509. DpImageAttributes *imageAttributes
  510. ) : DpOutputBilinearSpan(
  511. bitmap,
  512. scan,
  513. worldToDevice,
  514. context,
  515. imageAttributes
  516. )
  517. {
  518. InitializeFixedPointState();
  519. }
  520. virtual GpStatus OutputSpan(
  521. INT y,
  522. INT xMin,
  523. INT xMax
  524. );
  525. virtual BOOL IsValid() const
  526. {
  527. return (ScaleMatrixValid && DpOutputBilinearSpan::IsValid());
  528. }
  529. };
  530. //--------------------------------------------------------------------------
  531. // Textures - Identity transform
  532. //
  533. // Actually, this object handles texture output for any translating
  534. // transform, so long as the translate is integer.
  535. //
  536. //--------------------------------------------------------------------------
  537. class DpOutputBilinearSpan_Identity : public DpOutputBilinearSpan
  538. {
  539. protected:
  540. INT Dx;
  541. INT Dy;
  542. BOOL PowerOfTwo; // True if both texture dimensions power of two
  543. public:
  544. DpOutputBilinearSpan_Identity(
  545. const GpTexture *textureBrush,
  546. DpScanBuffer * scan,
  547. GpMatrix *worldToDevice,
  548. DpContext *context
  549. ) : DpOutputBilinearSpan(textureBrush, scan, worldToDevice, context)
  550. {
  551. PowerOfTwo = !(BmpData.Width & (BmpData.Width - 1)) &&
  552. !(BmpData.Height & (BmpData.Height - 1));
  553. // Compute the device-to-world transform (easy, eh?):
  554. Dx = -GpRound(worldToDevice->GetDx());
  555. Dy = -GpRound(worldToDevice->GetDy());
  556. }
  557. DpOutputBilinearSpan_Identity(
  558. const DpBitmap *bitmap,
  559. DpScanBuffer * scan,
  560. GpMatrix *worldToDevice,
  561. DpContext *context,
  562. DpImageAttributes *imageAttributes
  563. ) : DpOutputBilinearSpan(
  564. bitmap,
  565. scan,
  566. worldToDevice,
  567. context,
  568. imageAttributes
  569. )
  570. {
  571. PowerOfTwo = !(BmpData.Width & (BmpData.Width - 1)) &&
  572. !(BmpData.Height & (BmpData.Height - 1));
  573. // Compute the device-to-world transform (easy, eh?):
  574. Dx = -GpRound(worldToDevice->GetDx());
  575. Dy = -GpRound(worldToDevice->GetDy());
  576. }
  577. virtual GpStatus OutputSpan(
  578. INT y,
  579. INT xMin,
  580. INT xMax
  581. );
  582. };
  583. //--------------------------------------------------------------------------
  584. // Hatch brushes
  585. //--------------------------------------------------------------------------
  586. class DpOutputHatchSpan : public DpOutputSpan
  587. {
  588. public:
  589. DpScanBuffer * Scan;
  590. ARGB ForeARGB;
  591. ARGB BackARGB;
  592. ARGB AverageARGB;
  593. BYTE Data[8][8];
  594. protected:
  595. INT m_BrushOriginX;
  596. INT m_BrushOriginY;
  597. public:
  598. DpOutputHatchSpan(
  599. const GpHatch *hatchBrush,
  600. DpScanBuffer * scan,
  601. DpContext* context
  602. );
  603. virtual ~DpOutputHatchSpan()
  604. {
  605. }
  606. virtual GpStatus OutputSpan(
  607. INT y,
  608. INT xMin,
  609. INT xMax
  610. );
  611. virtual BOOL IsValid() const { return TRUE; }
  612. DpScanBuffer* GetScanBuffer(){ return Scan; }
  613. };
  614. class DpOutputStretchedHatchSpan : public DpOutputHatchSpan
  615. {
  616. public:
  617. DpOutputStretchedHatchSpan(
  618. const GpHatch *hatchBrush,
  619. DpScanBuffer * scan,
  620. DpContext* context,
  621. INT scaleFactor
  622. ) : DpOutputHatchSpan(hatchBrush,
  623. scan,
  624. context)
  625. {
  626. ScaleFactor = scaleFactor;
  627. }
  628. virtual GpStatus OutputSpan(
  629. INT y,
  630. INT xMin,
  631. INT xMax
  632. );
  633. private:
  634. INT ScaleFactor;
  635. };
  636. #endif // _OUTPUT_HPP