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.

261 lines
8.1 KiB

  1. /****************************************************************************
  2. SKEW.c
  3. The SKEW module handles rotating a rectangular object.
  4. ****************************************************************************/
  5. #include "stdafx.h"
  6. #include "global.h"
  7. #include "pbrush.h"
  8. #include "pbrusdoc.h"
  9. #include "imgwnd.h"
  10. #include "imgbrush.h"
  11. #include "imgsuprt.h"
  12. #include "bmobject.h"
  13. #include "undo.h"
  14. #include "props.h"
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static CHAR BASED_CODE THIS_FILE[] = __FILE__;
  18. #endif
  19. #include "memtrace.h"
  20. static int miAngle;
  21. /***************************************************************************/
  22. static int CalcOffset( int iValue )
  23. {
  24. // tan[angle] is the 100000/tangent of angles 1 to 89deg.
  25. static int invtan[90] = { -1, 5728996, 2863625, 1908114, 1430067,
  26. 1143005, 951436, 814436, 711537, 631375,
  27. 567128, 514455, 470463, 433148, 401078,
  28. 373205, 348741, 327085, 307768, 290421,
  29. 274748, 260509, 247509, 235585, 224604,
  30. 214451, 205030, 196261, 188073, 180405,
  31. 173205, 166428, 160034, 153987, 148256,
  32. 142815, 137638, 132705, 127994, 123490,
  33. 119175, 115037, 111061, 107237, 103553,
  34. 100000, 96569, 93252, 90040, 86929,
  35. 83910, 80978, 78129, 75355, 72654,
  36. 70021, 67451, 64941, 62487, 60086,
  37. 57735, 55431, 53171, 50953, 48773,
  38. 46631, 44523, 42448, 40403, 38386,
  39. 36397, 34433, 32492, 30573, 28675,
  40. 26795, 24933, 23087, 21256, 19438,
  41. 17633, 15838, 14054, 12279, 10510,
  42. 8749, 6993, 5241, 3492, 1746 };
  43. return (((iValue * 1000000 / invtan[miAngle]) + 5) / 10);
  44. }
  45. /***************************************************************************/
  46. void CImgWnd::CmdSkewBrush( int iAngle, BOOL bHorz )
  47. {
  48. BOOL bFullImage = FALSE;
  49. CDC* pdcImg = CDC::FromHandle( m_pImg->hDC );
  50. CDC* pdcSrc = &theImgBrush.m_dc;
  51. CRect rectSlct( 0, 0, theImgBrush.m_size.cx, theImgBrush.m_size.cy );
  52. if (theImgBrush.m_pImg == NULL && ! g_bCustomBrush)
  53. {
  54. bFullImage = TRUE;
  55. pdcSrc = pdcImg;
  56. rectSlct.SetRect( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight );
  57. }
  58. CRect rectSkew = rectSlct;
  59. if (!iAngle || rectSlct.IsRectEmpty() || abs(iAngle) > 89 || abs(iAngle) < 1 )
  60. return;
  61. if (! bFullImage)
  62. {
  63. PrepareForBrushChange( TRUE, TRUE );
  64. HideBrush();
  65. }
  66. // angle is the angle of skew 0 to 90 degrees
  67. // axis is the direction to skew TRUE: horizontal
  68. // the y axis moves by angle
  69. // FALSE: verticle
  70. // the x axis moves by angle
  71. int iWidthSlct = rectSlct.Width();
  72. int iHeightSlct = rectSlct.Height();
  73. miAngle = abs(iAngle);
  74. if (bHorz) // horizontal - create a new bitmap of size = x + y * tan (angle)
  75. rectSkew.right += CalcOffset( iHeightSlct );
  76. else // verticale - create a new bitmap of size = y + x * tan (angle)
  77. rectSkew.bottom += CalcOffset( iWidthSlct );
  78. int iWidthSkew = rectSkew.Width();
  79. int iHeightSkew = rectSkew.Height();
  80. // angle is the angle of skew 0 to 90 degrees
  81. // axis is the direction to skew TRUE: horizontal
  82. // the y axis moves by angle
  83. // FALSE: verticle
  84. // the x axis moves by angle
  85. CDC dcWork;
  86. CBitmap bmWork;
  87. CBrush brBackground;
  88. if (! dcWork.CreateCompatibleDC( pdcImg )
  89. || ! bmWork.CreateCompatibleBitmap( pdcImg, iWidthSkew, iHeightSkew )
  90. || ! brBackground.CreateSolidBrush( crRight ))
  91. {
  92. theApp.SetGdiEmergency( TRUE );
  93. return;
  94. }
  95. CBitmap* pbmOld = dcWork.SelectObject( &bmWork );
  96. CPalette* ppalOld = SetImgPalette( &dcWork, FALSE );
  97. dcWork.FillRect( rectSkew, &brBackground );
  98. CPalette* ppalOldSrc = SetImgPalette( pdcSrc, FALSE );
  99. // Skew the bitmap
  100. int mx = 1;
  101. int my = 1; // local variables for the skew
  102. int x = rectSlct.left;
  103. int y = rectSlct.top;
  104. BeginWaitCursor();
  105. if (bHorz) // horizontal
  106. {
  107. if (iAngle > 0)
  108. {
  109. mx = x + CalcOffset( iHeightSlct - y );
  110. // Start at Bottom
  111. for (y = rectSlct.bottom; y >= rectSlct.top; )
  112. {
  113. dcWork.BitBlt( mx, y, iWidthSlct, 1, pdcSrc, x, y, SRCCOPY );
  114. mx = x + CalcOffset( iHeightSlct - y-- );
  115. }
  116. }
  117. else
  118. {
  119. x = rectSkew.right - iWidthSlct;
  120. mx = x - CalcOffset( iHeightSlct - y );
  121. for (y = rectSlct.bottom; y >= rectSlct.top; )
  122. {
  123. dcWork.BitBlt( mx, y, iWidthSlct, 1, pdcSrc, rectSlct.left, y, SRCCOPY );
  124. mx = x - CalcOffset( iHeightSlct - y-- );
  125. }
  126. }
  127. }
  128. else
  129. { // vertical
  130. if (iAngle > 0)
  131. {
  132. my = y + CalcOffset( iWidthSlct - x );
  133. // Start at left
  134. for (x = rectSlct.left - 1; x <= rectSlct.right; )
  135. {
  136. dcWork.BitBlt( x, my, 1, iHeightSlct, pdcSrc, x, y, SRCCOPY );
  137. my = y + CalcOffset( iWidthSlct - x++ );
  138. }
  139. }
  140. else
  141. {
  142. y = rectSkew.bottom - iHeightSlct;
  143. my = y - CalcOffset( iWidthSlct - x );
  144. for (x = rectSlct.left - 1; x <= rectSlct.right; )
  145. {
  146. dcWork.BitBlt( x, my, 1, iHeightSlct, pdcSrc, x, rectSlct.top, SRCCOPY );
  147. my = y - CalcOffset( iWidthSlct - x++ );
  148. }
  149. }
  150. }
  151. if (ppalOldSrc)
  152. pdcSrc->SelectPalette( ppalOldSrc, FALSE );
  153. if (bFullImage)
  154. {
  155. theUndo.BeginUndo( TEXT("Skew Bitmap") );
  156. m_pImg->m_pBitmapObj->SetSizeProp( P_Size, CSize( iWidthSkew, iHeightSkew ) );
  157. m_pImg->cxWidth = iWidthSkew;
  158. m_pImg->cyHeight = iHeightSkew;
  159. SetUndo( m_pImg );
  160. pdcImg->BitBlt( 0, 0, m_pImg->cxWidth, m_pImg->cyHeight, &dcWork, 0, 0, SRCCOPY );
  161. InvalImgRect ( m_pImg, &rectSkew );
  162. CommitImgRect( m_pImg, &rectSkew );
  163. FinishUndo( rectSkew );
  164. theUndo.EndUndo();
  165. DirtyImg( m_pImg );
  166. InvalidateRect( NULL );
  167. UpdateWindow();
  168. dcWork.SelectObject( pbmOld );
  169. bmWork.DeleteObject();
  170. }
  171. else
  172. {
  173. CBitmap bmMask;
  174. if (! bmMask.CreateBitmap( iWidthSkew, iHeightSkew, 1, 1, NULL ))
  175. {
  176. if (ppalOld)
  177. dcWork.SelectPalette( ppalOld, FALSE );
  178. theApp.SetMemoryEmergency( TRUE );
  179. return;
  180. }
  181. dcWork.SelectObject( pbmOld );
  182. theImgBrush.m_dc.SelectObject( &bmWork );
  183. theImgBrush.m_bitmap.DeleteObject();
  184. theImgBrush.m_bitmap.Attach( bmWork.Detach() );
  185. theImgBrush.m_size.cx = iWidthSkew;
  186. theImgBrush.m_size.cy = iHeightSkew;
  187. VERIFY( theImgBrush.m_maskDC.SelectObject( &bmMask ) ==
  188. &theImgBrush.m_maskBitmap );
  189. theImgBrush.m_maskBitmap.DeleteObject();
  190. theImgBrush.m_maskBitmap.Attach( bmMask.Detach() );
  191. theImgBrush.RecalcMask( crRight );
  192. rectSkew = theImgBrush.m_rcSelection;
  193. mx = 0;
  194. my = 0;
  195. if (bHorz)
  196. mx = CalcOffset( iHeightSlct ) / 2;
  197. else
  198. my = CalcOffset( iWidthSlct ) / 2;
  199. rectSkew.InflateRect( mx, my );
  200. MoveBrush( rectSkew );
  201. }
  202. if (ppalOld)
  203. dcWork.SelectPalette( ppalOld, FALSE );
  204. dcWork.DeleteDC();
  205. EndWaitCursor();
  206. }
  207. /***************************************************************************/