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.

226 lines
6.8 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: clip.c
  8. *
  9. * Clipping code.
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. *****************************************************************************/
  14. #include "precomp.h"
  15. #include "gdi.h"
  16. #include "clip.h"
  17. //----------------------------*Public*Routine-------------------------------
  18. // BOOL bIntersect
  19. //
  20. // Function:
  21. // Check the integration of two input rectangles (RECTL* pRcl1,
  22. // RECTL* pRcl2) and set the intersection result in (RECTL* pRclResult)
  23. //
  24. // Return:
  25. // TRUE---If 'prcl1' and 'prcl2' intersect. The intersection will be in
  26. // 'prclResult'
  27. // FALSE--If they don't intersect. 'prclResult' is undefined.
  28. //
  29. //---------------------------------------------------------------------------
  30. BOOL
  31. bIntersect(RECTL* pRcl1,
  32. RECTL* pRcl2,
  33. RECTL* pRclResult)
  34. {
  35. DBG_GDI((7, "bIntersect called--pRcl1=0x%x, pRcl2=0x%x, pRclResult=0x%x",
  36. pRcl1, pRcl2, pRclResult));
  37. pRclResult->left = max(pRcl1->left, pRcl2->left);
  38. pRclResult->right = min(pRcl1->right, pRcl2->right);
  39. //
  40. // Check if there an intersection horizontally
  41. //
  42. if ( pRclResult->left < pRclResult->right )
  43. {
  44. pRclResult->top = max(pRcl1->top, pRcl2->top);
  45. pRclResult->bottom = min(pRcl1->bottom, pRcl2->bottom);
  46. if (pRclResult->top < pRclResult->bottom)
  47. {
  48. //
  49. // Check if there an intersection vertically
  50. //
  51. return(TRUE);
  52. }
  53. }
  54. DBG_GDI((7, "bIntersect returned FALSE"));
  55. //
  56. // Return FALSE if there is no intersection
  57. //
  58. return(FALSE);
  59. }// bIntersect()
  60. //-----------------------------Public Routine-------------------------------
  61. // LONG cIntersect
  62. //
  63. // This routine takes a list of rectangles from 'pRclIn' and clips them
  64. // in-place to the rectangle 'pRclClip'. The input rectangles don't
  65. // have to intersect 'prclClip'; the return value will reflect the
  66. // number of input rectangles that did intersect, and the intersecting
  67. // rectangles will be densely packed.
  68. //
  69. //--------------------------------------------------------------------------
  70. LONG
  71. cIntersect(RECTL* pRclClip,
  72. RECTL* pRclIn,
  73. LONG lNumOfRecs)
  74. {
  75. LONG cIntersections;
  76. RECTL* pRclOut;
  77. DBG_GDI((7, "cIntersect called--pRclClip=0x%x, pRclIn=0x%x,lNumOfRecs=%ld",
  78. pRclClip, pRclIn, lNumOfRecs));
  79. cIntersections = 0;
  80. pRclOut = pRclIn; // Put the result in place as the input
  81. //
  82. // Validate input parameter
  83. //
  84. ASSERTDD( ((pRclIn != NULL ) && (pRclClip != NULL) && ( lNumOfRecs >= 0 )),
  85. "Wrong input to cIntersect" );
  86. for (; lNumOfRecs != 0; pRclIn++, lNumOfRecs--)
  87. {
  88. pRclOut->left = max(pRclIn->left, pRclClip->left);
  89. pRclOut->right = min(pRclIn->right, pRclClip->right);
  90. if ( pRclOut->left < pRclOut->right )
  91. {
  92. //
  93. // Find intersection, horizontally, between current rectangle and
  94. // the clipping rectangle.
  95. //
  96. pRclOut->top = max(pRclIn->top, pRclClip->top);
  97. pRclOut->bottom = min(pRclIn->bottom, pRclClip->bottom);
  98. if ( pRclOut->top < pRclOut->bottom )
  99. {
  100. //
  101. // Find intersection, vertically, between current rectangle and
  102. // the clipping rectangle. Put this rectangle in the result
  103. // list and increment the counter. Ready for next input
  104. //
  105. pRclOut++;
  106. cIntersections++;
  107. }
  108. }
  109. }// loop through all the input rectangles
  110. DBG_GDI((7, "cIntersect found %d intersections", cIntersections));
  111. return(cIntersections);
  112. }// cIntersect()
  113. //-----------------------------Public Routine-------------------------------
  114. // VOID vClipAndRender
  115. //
  116. // Clips the destination rectangle calling pfgn (the render function) as
  117. // appropriate.
  118. //
  119. // Argumentes needed from function block (GFNPB)
  120. //
  121. // pco------pointer to clip object
  122. // prclDst--pointer to destination rectangle
  123. // psurfDst-pointer to destination Surf
  124. // psurfSrc-pointer to destination Surf (NULL if no source)
  125. // pptlSrc--pointer to source point
  126. // prclSrc--pointer to source rectangle (used if pptlSrc == NULL)
  127. // pgfn-----pointer to render function
  128. //
  129. // NOTES:
  130. //
  131. // pptlSrc and prclSrc are only used if psurfSrc == psurfDst. If there is
  132. // no source psurfSrc must be set to NULL. If prclSrc is specified, pptlSrc
  133. // is not used.
  134. //
  135. //--------------------------------------------------------------------------
  136. VOID vClipAndRender(GFNPB * ppb)
  137. {
  138. CLIPOBJ * pco = ppb->pco;
  139. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  140. {
  141. ppb->pRects = ppb->prclDst;
  142. ppb->lNumRects = 1;
  143. ppb->pgfn(ppb);
  144. }
  145. else if (pco->iDComplexity == DC_RECT)
  146. {
  147. RECTL rcl;
  148. if (bIntersect(ppb->prclDst, &pco->rclBounds, &rcl))
  149. {
  150. ppb->pRects = &rcl;
  151. ppb->lNumRects = 1;
  152. ppb->pgfn(ppb);
  153. }
  154. }
  155. else
  156. {
  157. ClipEnum ce;
  158. LONG c;
  159. BOOL bMore;
  160. ULONG ulDir = CD_ANY;
  161. // determine direction if operation on same surface
  162. if(ppb->psurfDst == ppb->psurfSrc)
  163. {
  164. LONG lXSrc, lYSrc, offset;
  165. if(ppb->pptlSrc != NULL)
  166. {
  167. lXSrc = ppb->pptlSrc->x;
  168. lYSrc = ppb->pptlSrc->y;
  169. }
  170. else
  171. {
  172. lXSrc = ppb->prclSrc->left;
  173. lYSrc = ppb->prclSrc->top;
  174. }
  175. // NOTE: we can safely shift by 16 because the surface
  176. // stride will never be greater the 2--16
  177. offset = (ppb->prclDst->top - lYSrc) << 16;
  178. offset += (ppb->prclDst->left - lXSrc);
  179. if(offset > 0)
  180. ulDir = CD_LEFTUP;
  181. else
  182. ulDir = CD_RIGHTDOWN;
  183. }
  184. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, ulDir, 0);
  185. do
  186. {
  187. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  188. c = cIntersect(ppb->prclDst, ce.arcl, ce.c);
  189. if (c != 0)
  190. {
  191. ppb->pRects = ce.arcl;
  192. ppb->lNumRects = c;
  193. ppb->pgfn(ppb);
  194. }
  195. } while (bMore);
  196. }
  197. }