Source code of Windows XP (NT5)
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.

239 lines
6.6 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: CVPMFilter.cpp
  3. *
  4. *
  5. *
  6. *
  7. * Created: Tue 02/15/2000
  8. * Author: Glenn Evans [GlennE]
  9. *
  10. * Copyright (c) 2000 Microsoft Corporation
  11. \**************************************************************************/
  12. #include <streams.h>
  13. #include <DRect.h>
  14. #if 1
  15. #include <math.h>
  16. static double myfloor(double dNumber)
  17. {
  18. return floor( dNumber );
  19. }
  20. static double myceil(double dNumber)
  21. {
  22. return ceil( dNumber );
  23. }
  24. #else
  25. // have to define my own floor inorder to avoid pulling in the C runtime
  26. static double myfloor(double dNumber)
  27. {
  28. // cast it to LONGLONG to get rid of the fraction
  29. LONGLONG llNumber = (LONGLONG)dNumber;
  30. if ((dNumber > 0) && ((double)llNumber > dNumber))
  31. {
  32. // need to push ccNumber towards zero (eg 5.7)
  33. return (double)(llNumber-1);
  34. }
  35. else if ((dNumber < 0) && ((double)llNumber < dNumber))
  36. {
  37. // need to push ccNumber towards zero (eg -5.7)
  38. return (double)(llNumber+1);
  39. }
  40. else
  41. {
  42. // numbers like 5.3 or -5.3
  43. return (double)(llNumber);
  44. }
  45. }
  46. // have to define my own ceil inorder to avoid pulling in the C runtime
  47. static double myceil(double dNumber)
  48. {
  49. // cast it to LONGLONG to get rid of the fraction
  50. LONGLONG llNumber = (LONGLONG)dNumber;
  51. if ((dNumber > 0) && ((double)llNumber < dNumber))
  52. {
  53. // need to push ccNumber away from zero (eg 5.3)
  54. return (double)(llNumber+1);
  55. }
  56. else if ((dNumber < 0) && ((double)llNumber > dNumber))
  57. {
  58. // need to push ccNumber away from zero (eg -5.3)
  59. return (double)(llNumber-1);
  60. }
  61. else
  62. {
  63. // numbers like 5.7 or -5.7
  64. return (double)(llNumber);
  65. }
  66. }
  67. #endif
  68. // this in a way defines the error margin
  69. #define EPSILON 0.0001
  70. // this is a function implemented solely to handle floating point rounding errors.
  71. // dEpsilon defines the error margin. So if a floating point number is within I-e, I+e (inclusive)
  72. // (I is an integer, e is dEpsilon), we return its floor as I itself, otherwise we go to the
  73. // base defintion of myfloor
  74. static double myfloor(double dNumber, double dEpsilon)
  75. {
  76. if (dNumber > dEpsilon)
  77. return myfloor(dNumber + dEpsilon);
  78. else if (dNumber < -dEpsilon)
  79. return myfloor(dNumber - dEpsilon);
  80. else
  81. return 0;
  82. }
  83. // this is a function implemented solely to handle floating point rounding errors.
  84. // dEpsilon defines the error margin. So if a floating point number is within I-e, I+e (inclusive)
  85. // (I is an integer, e is dEpsilon), we return its ceil as I itself, otherwise we go to the
  86. // base defintion of myceil
  87. static double myceil(double dNumber, double dEpsilon)
  88. {
  89. if (dNumber > dEpsilon)
  90. return myceil(dNumber - dEpsilon);
  91. else if (dNumber < -dEpsilon)
  92. return myceil(dNumber + dEpsilon);
  93. else
  94. return 0;
  95. }
  96. DRect::DRect( const RECT& rc )
  97. : m_left( rc.left )
  98. , m_right( rc.right )
  99. , m_top( rc.top )
  100. , m_bottom( rc.bottom )
  101. {
  102. }
  103. RECT DRect::AsRECT() const
  104. {
  105. RECT rRect;
  106. rRect.left = (LONG)myfloor(m_left, EPSILON);
  107. rRect.top = (LONG)myfloor(m_top, EPSILON);
  108. rRect.right = (LONG)myceil(m_right, EPSILON);
  109. rRect.bottom = (LONG)myceil(m_bottom, EPSILON);
  110. return rRect;
  111. }
  112. DRect DRect::IntersectWith( const DRect& drect ) const
  113. {
  114. return DRect(
  115. max( drect.m_left, m_left), max( drect.m_top, m_top),
  116. min( drect.m_right, m_right), min( drect.m_bottom, m_bottom));
  117. }
  118. // just a helper function to scale a DRECT
  119. void DRect::Scale( double dScaleX, double dScaleY )
  120. {
  121. m_left *= dScaleX;
  122. m_right *= dScaleX;
  123. m_top *= dScaleY;
  124. m_bottom *= dScaleY;
  125. }
  126. // just a helper function, to get the letterboxed or cropped rect
  127. // Puts the transformed rectangle into pRect.
  128. double DRect::CorrectAspectRatio( double dPictAspectRatio, BOOL bShrink )
  129. {
  130. double dWidth, dHeight, dNewWidth, dNewHeight;
  131. dNewWidth = dWidth = GetWidth();
  132. dNewHeight = dHeight = GetHeight();
  133. ASSERT( dWidth > 0 );
  134. ASSERT( dHeight > 0 );
  135. double dResolutionRatio = dWidth / dHeight;
  136. double dTransformRatio = dPictAspectRatio / dResolutionRatio;
  137. // shrinks one dimension to maintain the coorect aspect ratio
  138. if ( bShrink ) {
  139. if (dTransformRatio > 1.0) {
  140. dNewHeight = dNewHeight / dTransformRatio;
  141. } else if (dTransformRatio < 1.0) {
  142. dNewWidth = dNewWidth * dTransformRatio;
  143. }
  144. } // stretches one dimension to maintain the coorect aspect ratio
  145. else {
  146. if (dTransformRatio > 1.0) {
  147. dNewWidth = dNewWidth * dTransformRatio;
  148. } else if (dTransformRatio < 1.0) {
  149. dNewHeight = dNewHeight / dTransformRatio;
  150. }
  151. }
  152. // cut or add equal portions to the changed dimension
  153. m_left += (dWidth - dNewWidth)/2.0;
  154. m_right = m_left + dNewWidth;
  155. m_top += (dHeight - dNewHeight)/2.0;
  156. m_bottom = m_top + dNewHeight;
  157. return dTransformRatio;
  158. }
  159. /******************************Private*Routine******************************\
  160. * ClipWith
  161. *
  162. * Clip a destination rectangle & update the scaled source accordingly
  163. *
  164. *
  165. * History:
  166. * Fri 04/07/2000 - GlennE - Created
  167. *
  168. \**************************************************************************/
  169. void
  170. DRect::ClipWith(const DRect& rdWith, DRect *pUpdate )
  171. {
  172. // figure out src/dest scale ratios
  173. double dUpdateWidth = pUpdate->GetWidth();
  174. double dUpdateHeight = pUpdate->GetHeight();
  175. double dDestWidth = GetWidth();
  176. double dDestHeight = GetHeight();
  177. // clip destination (and adjust the source when we change the destination)
  178. // see if we have to clip horizontally
  179. if( dDestWidth ) {
  180. if( rdWith.m_left > m_left ) {
  181. double dDelta = rdWith.m_left - m_left;
  182. m_left += dDelta;
  183. double dDeltaSrc = dDelta*dUpdateWidth/dDestWidth;
  184. pUpdate->m_left += dDeltaSrc;
  185. }
  186. if( rdWith.m_right < m_right ) {
  187. double dDelta = m_right-rdWith.m_right;
  188. m_right -= dDelta;
  189. double dDeltaSrc = dDelta*dUpdateWidth/dDestWidth;
  190. pUpdate->m_right -= dDeltaSrc;
  191. }
  192. }
  193. // see if we have to clip vertically
  194. if( dDestHeight ) {
  195. if( rdWith.m_top > m_top ) {
  196. double dDelta = rdWith.m_top - m_top;
  197. m_top += dDelta;
  198. double dDeltaSrc = dDelta*dUpdateHeight/dDestHeight;
  199. pUpdate->m_top += dDeltaSrc;
  200. }
  201. if( rdWith.m_bottom < m_bottom ) {
  202. double dDelta = m_bottom-rdWith.m_bottom;
  203. m_bottom -= dDelta;
  204. double dDeltaSrc = dDelta*dUpdateHeight/dDestHeight;
  205. pUpdate->m_bottom -= dDeltaSrc;
  206. }
  207. }
  208. }