XTPMarkupDrawingContext.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:24k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPMarkupDrawingContext.cpp: implementation of the CXTPMarkupDrawingContext class.
  2. //
  3. // This file is a part of the XTREME TOOLKIT PRO MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include <math.h>
  22. #include "Common/XTPImageManager.h"
  23. #include "Common/XTPvc80Helpers.h"
  24. #include "XTPMarkupDrawingContext.h"
  25. #include "XTPMarkupContext.h"
  26. #ifdef _DEBUG
  27. #undef THIS_FILE
  28. static char THIS_FILE[]=__FILE__;
  29. #define new DEBUG_NEW
  30. #endif
  31. //////////////////////////////////////////////////////////////////////
  32. // Construction/Destruction
  33. //////////////////////////////////////////////////////////////////////
  34. CXTPMarkupDrawingContext::CXTPMarkupDrawingContext(HDC hDC)
  35. {
  36. m_hDC = hDC;
  37. m_bDeleteDC = FALSE;
  38. Init();
  39. }
  40. CXTPMarkupDrawingContext::CXTPMarkupDrawingContext()
  41. {
  42. m_hDC = CreateCompatibleDC(0);
  43. m_bDeleteDC = TRUE;
  44. Init();
  45. }
  46. void CXTPMarkupDrawingContext::Init()
  47. {
  48. m_hAttribDC = m_hDC;
  49. m_pSelectedFont = NULL;
  50. m_hOldFont = NULL;
  51. ::GetWindowExtEx(m_hDC, &m_sizeWinExt);
  52. ::GetViewportExtEx(m_hDC, &m_sizeVpExt);
  53. ::GetViewportOrgEx(m_hDC, &m_ptViewortOrg);
  54. m_rcClipBox.SetRectEmpty();
  55. ::GetClipBox(m_hDC, &m_rcClipBox);
  56. ::SetBkMode(m_hDC, TRANSPARENT);
  57. }
  58. CXTPMarkupDrawingContext::~CXTPMarkupDrawingContext()
  59. {
  60. SetFont(NULL);
  61. if (m_bDeleteDC)
  62. {
  63. DeleteDC(m_hDC);
  64. }
  65. }
  66. POINT CXTPMarkupDrawingContext::TranslatePoint(const POINT& ptVisualOffset) const
  67. {
  68. POINT pt;
  69. pt.x = MulDiv(ptVisualOffset.x, abs(m_sizeVpExt.cx), abs(m_sizeWinExt.cx));
  70. pt.y = MulDiv(ptVisualOffset.y, abs(m_sizeVpExt.cy), abs(m_sizeWinExt.cy));
  71. return pt;
  72. }
  73. HDC CXTPMarkupDrawingContext::Detach()
  74. {
  75. SetFont(NULL);
  76. HDC hDC = m_hDC;
  77. m_hDC = NULL;
  78. return hDC;
  79. }
  80. void CXTPMarkupDrawingContext::SetViewportOrg(const POINT& ptViewortOrg)
  81. {
  82. SetViewportOrgEx(m_hDC, ptViewortOrg.x, ptViewortOrg.y, NULL);
  83. }
  84. POINT CXTPMarkupDrawingContext::OffsetViewport(const POINT& ptVisualOffset)
  85. {
  86. POINT ptViewortOrg = m_ptViewortOrg;
  87. POINT pt = TranslatePoint(ptVisualOffset);
  88. m_ptViewortOrg.x += pt.x;
  89. m_ptViewortOrg.y += pt.y;
  90. ::SetViewportOrgEx(m_hDC, m_ptViewortOrg.x, m_ptViewortOrg.y, NULL);
  91. ::GetClipBox(m_hDC, &m_rcClipBox);
  92. return ptViewortOrg;
  93. }
  94. void CXTPMarkupDrawingContext::SetViewport(const POINT& ptViewortOrg)
  95. {
  96. m_ptViewortOrg = ptViewortOrg;
  97. ::SetViewportOrgEx(m_hDC, m_ptViewortOrg.x, m_ptViewortOrg.y, NULL);
  98. ::GetClipBox(m_hDC, &m_rcClipBox);
  99. }
  100. HRGN CXTPMarkupDrawingContext::SaveClipRegion()
  101. {
  102. HRGN hrgnClip = ::CreateRectRgn(0, 0, 0, 0);
  103. if (hrgnClip != NULL)
  104. {
  105. if (GetClipRgn(m_hDC, hrgnClip) != 1)
  106. {
  107. DeleteObject(hrgnClip);
  108. hrgnClip = (HRGN)-1;
  109. }
  110. }
  111. return hrgnClip;
  112. }
  113. void CXTPMarkupDrawingContext::IntersectClipRect(const RECT& rcLayoutClip)
  114. {
  115. ::IntersectClipRect(m_hDC, rcLayoutClip.left, rcLayoutClip.top, rcLayoutClip.right, rcLayoutClip.bottom);
  116. ::GetClipBox(m_hDC, m_rcClipBox);
  117. }
  118. void CXTPMarkupDrawingContext::RestoreClipRegion(HRGN hrgnClip)
  119. {
  120. if (hrgnClip != NULL)
  121. {
  122. if (hrgnClip == (HRGN)-1)
  123. {
  124. ExtSelectClipRgn(m_hDC, NULL, RGN_COPY);
  125. }
  126. else
  127. {
  128. ExtSelectClipRgn(m_hDC, hrgnClip, RGN_COPY);
  129. DeleteObject(hrgnClip);
  130. }
  131. ::GetClipBox(m_hDC, m_rcClipBox);
  132. }
  133. }
  134. void CXTPMarkupDrawingContext::FillSolidRect(CRect rc, COLORREF clr)
  135. {
  136. CXTPMarkupSolidColorBrush brush(clr);
  137. brush.FillRect(this, rc);
  138. }
  139. void CXTPMarkupDrawingContext::DrawRectangle(CXTPMarkupBrush* pBrush, CRect rc)
  140. {
  141. pBrush->FillRect(this, rc);
  142. }
  143. void CXTPMarkupDrawingContext::DrawFrame(CXTPMarkupBrush* pBrush, CRect rc)
  144. {
  145. pBrush->FillRect(this, CRect(rc.left, rc.top, rc.right, rc.top + 1));
  146. pBrush->FillRect(this, CRect(rc.left, rc.top, rc.left + 1, rc.bottom));
  147. pBrush->FillRect(this, CRect(rc.left, rc.bottom - 1, rc.right, rc.bottom));
  148. pBrush->FillRect(this, CRect(rc.right - 1, rc.top, rc.right, rc.bottom));
  149. }
  150. void CXTPMarkupDrawingContext::DrawTextLine(LPCWSTR lpszText, UINT nCount, LPCRECT lpRect)
  151. {
  152. ::ExtTextOutW(m_hDC, lpRect->left, lpRect->top, 0, lpRect, lpszText, nCount, 0);
  153. }
  154. void CXTPMarkupDrawingContext::SetFont(CXTPMarkupFont* pFont)
  155. {
  156. if (!m_hDC)
  157. return;
  158. if (m_pSelectedFont == pFont)
  159. return;
  160. if (pFont == NULL && m_hOldFont)
  161. {
  162. SelectFontObject(m_hOldFont);
  163. m_hOldFont = NULL;
  164. }
  165. else if (pFont != NULL && m_hOldFont == NULL)
  166. {
  167. m_hOldFont = SelectFontObject(pFont->m_hFont);
  168. }
  169. else if (pFont != NULL)
  170. {
  171. SelectFontObject(pFont->m_hFont);
  172. }
  173. MARKUP_RELEASE(m_pSelectedFont);
  174. m_pSelectedFont = pFont;
  175. MARKUP_ADDREF(m_pSelectedFont);
  176. }
  177. SIZE CXTPMarkupDrawingContext::GetTextExtent(LPCWSTR lpszText, int nCount) const
  178. {
  179. SIZE sz;
  180. VERIFY(::GetTextExtentPoint32W(m_hAttribDC, lpszText, nCount, &sz));
  181. return sz;
  182. }
  183. HFONT CXTPMarkupDrawingContext::SelectFontObject(HFONT hFont)
  184. {
  185. HFONT hOldObj = 0;
  186. if (m_hDC != m_hAttribDC)
  187. hOldObj = (HFONT)::SelectObject(m_hDC, hFont);
  188. if (m_hAttribDC != NULL)
  189. hOldObj = (HFONT)::SelectObject(m_hAttribDC, hFont);
  190. return hOldObj;
  191. }
  192. CXTPMarkupPrintingContext::CXTPMarkupPrintingContext(HDC hDC, HDC hAttribDC)
  193. : CXTPMarkupDrawingContext(hDC)
  194. {
  195. m_hAttribDC = hAttribDC;
  196. }
  197. void CXTPMarkupPrintingContext::DrawTextLine(LPCWSTR lpszString, UINT nCount, LPCRECT lpRect)
  198. {
  199. if (m_hAttribDC == m_hDC)
  200. {
  201. ::ExtTextOutW(m_hDC, lpRect->left, lpRect->top, 0, lpRect, lpszString, nCount, 0);
  202. return;
  203. }
  204. LPINT lpDxWidths = NULL;
  205. ASSERT(m_hDC != NULL);
  206. ASSERT(m_hAttribDC != NULL);
  207. ASSERT(lpszString != NULL);
  208. ASSERT(lpDxWidths == NULL ||
  209. AfxIsValidAddress(lpDxWidths, sizeof(int) * nCount, FALSE));
  210. ASSERT(AfxIsValidAddress(lpszString, nCount, FALSE));
  211. int* pDeltas = NULL;
  212. LPWSTR pOutputString = NULL;
  213. int nRightFixup = 0;
  214. if (nCount == 0)    // Do nothing
  215. return;
  216. pDeltas = new int[nCount];
  217. pOutputString = new WCHAR[nCount];
  218. int x = lpRect->left;
  219. ComputeDeltas(x, (LPWSTR)lpszString, nCount, FALSE, 0, NULL, 0,
  220. pOutputString, pDeltas, nRightFixup);
  221. lpDxWidths = pDeltas;
  222. lpszString = pOutputString;
  223. ::ExtTextOutW(m_hDC, x, lpRect->top, 0, lpRect, lpszString, nCount, lpDxWidths);
  224. delete[] pDeltas;
  225. delete[] pOutputString;
  226. }
  227. int CXTPMarkupPrintingContext::ComputeNextTab(int x, UINT nTabStops, LPINT lpnTabStops,
  228. int nTabOrigin, int nTabWidth) const
  229. {
  230. x -= nTabOrigin;        // normalize position to tab origin
  231. for (UINT i = 0; i < nTabStops; i++, lpnTabStops++)
  232. {
  233. if (*lpnTabStops > x)
  234. return *lpnTabStops + nTabOrigin;
  235. }
  236. return (x / nTabWidth + 1) * nTabWidth + nTabOrigin;
  237. }
  238. CSize CXTPMarkupPrintingContext::ComputeDeltas(int& x, LPCWSTR lpszString, UINT &nCount,
  239. BOOL bTabbed, UINT nTabStops, LPINT lpnTabStops, int nTabOrigin,
  240. LPWSTR lpszOutputString, int* pnDxWidths, int& nRightFixup) const
  241. {
  242. TEXTMETRIC tmAttrib;
  243. TEXTMETRIC tmScreen;
  244. ::GetTextMetrics(m_hAttribDC, &tmAttrib);
  245. ::GetTextMetrics(m_hDC, &tmScreen);
  246. CSize sizeExtent;
  247. ::GetTextExtentPoint32A(m_hAttribDC, "A", 1, &sizeExtent);
  248. CPoint ptCurrent;
  249. UINT nAlignment = ::GetTextAlign(m_hAttribDC);
  250. BOOL bUpdateCP = (nAlignment & TA_UPDATECP) != 0;
  251. if (bUpdateCP)
  252. {
  253. ::GetCurrentPositionEx(m_hDC, &ptCurrent);
  254. x = ptCurrent.x;
  255. }
  256. LPCWSTR lpszCurChar = lpszString;
  257. LPCWSTR lpszStartRun = lpszString;
  258. int* pnCurDelta = pnDxWidths;
  259. int nStartRunPos = x;
  260. int nCurrentPos = x;
  261. int nStartOffset = 0;
  262. int nTabWidth = 0;
  263. if (bTabbed)
  264. {
  265. if (nTabStops == 1)
  266. {
  267. nTabWidth = lpnTabStops[0];
  268. }
  269. else
  270. {
  271. // Get default size of a tab
  272. nTabWidth = LOWORD(::GetTabbedTextExtentA(m_hAttribDC,
  273. "t", 1, 0, NULL));
  274. }
  275. }
  276. for (UINT i = 0; i < nCount; i++)
  277. {
  278. BOOL bSpace = ((_TUCHAR)*lpszCurChar == (_TUCHAR)tmAttrib.tmBreakChar);
  279. if (bSpace || (bTabbed && *lpszCurChar == 't'))
  280. {
  281. // bSpace will be either TRUE (==1) or FALSE (==0).  For spaces
  282. // we want the space included in the GetTextExtent, for tabs we
  283. // do not want the tab included
  284. int nRunLength = (int)(lpszCurChar - lpszStartRun) + (bSpace ? 1 : 0);
  285. CSize sizeExtent2;
  286. ::GetTextExtentPoint32W(m_hAttribDC, lpszStartRun, nRunLength,
  287. &sizeExtent2);
  288. int nNewPos = nStartRunPos + sizeExtent2.cx
  289. - tmAttrib.tmOverhang;
  290. // now, if this is a Tab (!bSpace), compute the next tab stop
  291. if (!bSpace)
  292. {
  293. nNewPos = ComputeNextTab(nNewPos, nTabStops, lpnTabStops,
  294. nTabOrigin, nTabWidth);
  295. }
  296. // Add this width to previous width
  297. if (pnCurDelta == pnDxWidths)
  298. nStartOffset += nNewPos - nCurrentPos;
  299. else
  300. *(pnCurDelta-1) += nNewPos - nCurrentPos;
  301. nCurrentPos = nNewPos;
  302. nStartRunPos = nCurrentPos;     // set start of run
  303. // *lpszCurChar must be SBC: tmBreakChar or 't'
  304. lpszStartRun = lpszCurChar + 1;
  305. }
  306. else
  307. {
  308. // For the non-tabbed or non-tab-character case
  309. int cxScreen;
  310. if (_istlead(*lpszCurChar))
  311. {
  312. cxScreen = tmScreen.tmAveCharWidth;
  313. *pnCurDelta = tmAttrib.tmAveCharWidth;
  314. }
  315. else
  316. {
  317. ::GetCharWidth(m_hDC, (_TUCHAR)*lpszCurChar,
  318. (_TUCHAR)*lpszCurChar, &cxScreen);
  319. if (!::GetCharWidth(m_hAttribDC, (_TUCHAR)*lpszCurChar,
  320. (_TUCHAR)*lpszCurChar, pnCurDelta))
  321. {
  322. // If printer driver fails the above call, use the average width
  323. *pnCurDelta = tmAttrib.tmAveCharWidth;
  324. }
  325. }
  326. *pnCurDelta -= tmAttrib.tmOverhang;
  327. cxScreen -= tmScreen.tmOverhang;
  328. nCurrentPos += *pnCurDelta;     // update current position
  329. // Center character in allotted space
  330. if (pnCurDelta != pnDxWidths)
  331. {
  332. int diff = (*pnCurDelta - cxScreen) / 2;
  333. *pnCurDelta -= diff;
  334. *(pnCurDelta - 1) += diff;
  335. }
  336. *lpszOutputString++ = *lpszCurChar;
  337. if (_istlead(*lpszCurChar))
  338. {
  339. *lpszOutputString++ = *(lpszCurChar+1); // copy trailing byte
  340. *(pnCurDelta + 1) = *pnCurDelta;        // double wide
  341. nCurrentPos += *pnCurDelta;
  342. pnCurDelta++;
  343. i++;
  344. }
  345. pnCurDelta++;
  346. }
  347. lpszCurChar++;
  348. }
  349. nAlignment &= TA_CENTER|TA_RIGHT;
  350. sizeExtent.cx = nCurrentPos - x;
  351. nRightFixup = 0;
  352. if (nAlignment == TA_LEFT)
  353. x += nStartOffset;      // Full left side adjustment
  354. else if (nAlignment == TA_CENTER)
  355. x += nStartOffset/2;    // Adjust Center by 1/2 left side adjustment
  356. else if (nAlignment == TA_RIGHT)
  357. nRightFixup = nStartOffset; // Right adjust needed later if TA_UPDATECP
  358. if (bUpdateCP)
  359. ::MoveToEx(m_hDC, x, ptCurrent.y, NULL);
  360. nCount = (UINT)(pnCurDelta - pnDxWidths);   // number of characters output
  361. return sizeExtent;
  362. }
  363. //////////////////////////////////////////////////////////////////////////
  364. // CXTPMarkupBrush
  365. IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupBrush, CXTPMarkupObject);
  366. void CXTPMarkupBrush::RegisterMarkupClass()
  367. {
  368. }
  369. void CXTPMarkupBrush::FillRect(CXTPMarkupDrawingContext* /*pDC*/, CRect /*rc*/)
  370. {
  371. }
  372. COLORREF CXTPMarkupBrush::GetHintColor() const
  373. {
  374. return 0;
  375. }
  376. CXTPMarkupObject* CXTPMarkupBrush::ConvertFrom(CXTPMarkupObject* pObject) const
  377. {
  378. if (IsStringObject(pObject))
  379. {
  380. COLORREF clr;
  381. if (CXTPMarkupColor::ConvertFromString(*((CXTPMarkupString*)pObject), clr))
  382. {
  383. return new CXTPMarkupSolidColorBrush(clr);
  384. }
  385. }
  386. return NULL;
  387. }
  388. //////////////////////////////////////////////////////////////////////////
  389. // CXTPMarkupSolidColorBrush
  390. CXTPMarkupDependencyProperty* CXTPMarkupSolidColorBrush::m_pColorProperty = NULL;
  391. IMPLEMENT_MARKUPCLASS(L"SolidColorBrush", CXTPMarkupSolidColorBrush, CXTPMarkupBrush);
  392. void CXTPMarkupSolidColorBrush::RegisterMarkupClass()
  393. {
  394. m_pColorProperty = CXTPMarkupDependencyProperty::Register(L"Color", MARKUP_TYPE(CXTPMarkupColor), MARKUP_TYPE(CXTPMarkupSolidColorBrush));
  395. }
  396. CXTPMarkupSolidColorBrush::CXTPMarkupSolidColorBrush()
  397. {
  398. }
  399. CXTPMarkupSolidColorBrush::CXTPMarkupSolidColorBrush(COLORREF clr)
  400. {
  401. SetValue(m_pColorProperty, new CXTPMarkupColor(clr));
  402. }
  403. BOOL CXTPMarkupSolidColorBrush::IsEqual(const CXTPMarkupObject* pObject) const
  404. {
  405. if (!pObject)
  406. return FALSE;
  407. if (pObject->GetType() != MARKUP_TYPE(CXTPMarkupSolidColorBrush))
  408. return FALSE;
  409. return GetHintColor() == ((CXTPMarkupSolidColorBrush*)pObject)->GetHintColor();
  410. }
  411. void CXTPMarkupSolidColorBrush::FillRect(CXTPMarkupDrawingContext* pDC, CRect rc)
  412. {
  413. CXTPMarkupColor* pColor = MARKUP_STATICCAST(CXTPMarkupColor, GetValue(m_pColorProperty));
  414. if (pColor)
  415. {
  416. COLORREF clrOld = ::SetBkColor(pDC->GetSafeHdc(), *pColor);
  417. ::ExtTextOut(pDC->GetSafeHdc(), 0, 0, ETO_OPAQUE, rc, NULL, 0, NULL);
  418. ::SetBkColor(pDC->GetSafeHdc(), clrOld);
  419. }
  420. }
  421. COLORREF CXTPMarkupSolidColorBrush::GetHintColor() const
  422. {
  423. CXTPMarkupColor* pColor = MARKUP_STATICCAST(CXTPMarkupColor, GetValue(m_pColorProperty));
  424. if (pColor)
  425. {
  426. return *pColor;
  427. }
  428. return 0;
  429. }
  430. //////////////////////////////////////////////////////////////////////////
  431. // CXTPMarkupPoint
  432. IMPLEMENT_MARKUPCLASS(NULL, CXTPMarkupPoint, CXTPMarkupObject);
  433. void CXTPMarkupPoint::RegisterMarkupClass()
  434. {
  435. }
  436. CXTPMarkupPoint::CXTPMarkupPoint()
  437. {
  438. x = 0;
  439. y = 0;
  440. }
  441. CXTPMarkupPoint::CXTPMarkupPoint(double x, double y)
  442. {
  443. this->x = x;
  444. this->y = y;
  445. }
  446. CXTPMarkupPoint& CXTPMarkupPoint::operator=(const CXTPMarkupPoint& srcPoint)
  447. {
  448. x = srcPoint.x;
  449. y = srcPoint.y;
  450. return *this;
  451. }
  452. CXTPMarkupObject* CXTPMarkupPoint::ConvertFrom(CXTPMarkupObject* pObject) const
  453. {
  454. if (IsStringObject(pObject))
  455. {
  456. LPCWSTR lpszValue = *(CXTPMarkupString*)pObject;
  457. float x = 0 , y = 0;
  458. if (WSCANF_S(lpszValue, L"%f,%f", &x, &y) != 2)
  459. return FALSE;
  460. return new CXTPMarkupPoint(x, y);
  461. }
  462. return FALSE;
  463. }
  464. //////////////////////////////////////////////////////////////////////////
  465. // CXTPMarkupGradientStop
  466. CXTPMarkupDependencyProperty* CXTPMarkupGradientStop::m_pColorProperty = NULL;
  467. CXTPMarkupDependencyProperty* CXTPMarkupGradientStop::m_pOffsetProperty = NULL;
  468. IMPLEMENT_MARKUPCLASS(L"GradientStop", CXTPMarkupGradientStop, CXTPMarkupObject);
  469. void CXTPMarkupGradientStop::RegisterMarkupClass()
  470. {
  471. m_pColorProperty = CXTPMarkupDependencyProperty::Register(L"Color", MARKUP_TYPE(CXTPMarkupColor), MARKUP_TYPE(CXTPMarkupGradientStop));
  472. m_pOffsetProperty = CXTPMarkupDependencyProperty::Register(L"Offset", MARKUP_TYPE(CXTPMarkupDouble), MARKUP_TYPE(CXTPMarkupGradientStop));
  473. }
  474. CXTPMarkupGradientStop::CXTPMarkupGradientStop()
  475. {
  476. }
  477. CXTPMarkupGradientStop::CXTPMarkupGradientStop(COLORREF clr, double dOffset)
  478. {
  479. SetValue(m_pColorProperty, new CXTPMarkupColor(clr));
  480. SetValue(m_pOffsetProperty, new CXTPMarkupDouble(dOffset));
  481. }
  482. COLORREF CXTPMarkupGradientStop::GetColor() const
  483. {
  484. CXTPMarkupColor* pColor = MARKUP_STATICCAST(CXTPMarkupColor, GetValue(m_pColorProperty));
  485. return pColor != NULL ? (COLORREF)*pColor : 0;
  486. }
  487. double CXTPMarkupGradientStop::GetOffset() const
  488. {
  489. CXTPMarkupDouble* pOffset = MARKUP_STATICCAST(CXTPMarkupDouble, GetValue(m_pOffsetProperty));
  490. return pOffset != NULL ? (double)*pOffset : 0.0;
  491. }
  492. CXTPMarkupGradientStops::CXTPMarkupGradientStops()
  493. {
  494. m_pElementType = MARKUP_TYPE(CXTPMarkupGradientStop);
  495. }
  496. //////////////////////////////////////////////////////////////////////////
  497. // CXTPMarkupLinearGradientBrush
  498. CXTPMarkupDependencyProperty* CXTPMarkupLinearGradientBrush::m_pStartPointProperty = NULL;
  499. CXTPMarkupDependencyProperty* CXTPMarkupLinearGradientBrush::m_pEndPointProperty = NULL;
  500. IMPLEMENT_MARKUPCLASS(L"LinearGradientBrush", CXTPMarkupLinearGradientBrush, CXTPMarkupBrush);
  501. void CXTPMarkupLinearGradientBrush::RegisterMarkupClass()
  502. {
  503. m_pStartPointProperty = CXTPMarkupDependencyProperty::Register(L"StartPoint", MARKUP_TYPE(CXTPMarkupPoint), MARKUP_TYPE(CXTPMarkupLinearGradientBrush));
  504. m_pEndPointProperty = CXTPMarkupDependencyProperty::Register(L"EndPoint", MARKUP_TYPE(CXTPMarkupPoint), MARKUP_TYPE(CXTPMarkupLinearGradientBrush));
  505. }
  506. CXTPMarkupLinearGradientBrush::CXTPMarkupLinearGradientBrush()
  507. {
  508. m_pGradientStops = new CXTPMarkupGradientStops();
  509. }
  510. CXTPMarkupLinearGradientBrush::CXTPMarkupLinearGradientBrush(CXTPMarkupGradientStops* pGradientStops)
  511. {
  512. m_pGradientStops = pGradientStops;
  513. }
  514. CXTPMarkupLinearGradientBrush::~CXTPMarkupLinearGradientBrush()
  515. {
  516. MARKUP_RELEASE(m_pGradientStops);
  517. }
  518. void CXTPMarkupLinearGradientBrush::SetStartPoint(double x, double y)
  519. {
  520. SetValue(m_pStartPointProperty, new CXTPMarkupPoint(x, y));
  521. }
  522. void CXTPMarkupLinearGradientBrush::SetEndPoint(double x, double y)
  523. {
  524. SetValue(m_pEndPointProperty, new CXTPMarkupPoint(x, y));
  525. }
  526. void CXTPMarkupLinearGradientBrush::SetContentObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pContent)
  527. {
  528. m_pGradientStops->SetContentObject(pBuilder, pContent);
  529. }
  530. int _cdecl CXTPMarkupLinearGradientBrush::_GradientStopCompare(const void *arg1, const void *arg2)
  531. {
  532. double& dOffset1 = ((GRADIENTSTOP*)arg1)->dOffset;
  533. double& dOffset2 = ((GRADIENTSTOP*)arg2)->dOffset;
  534. return dOffset1 > dOffset2 ? 1 : dOffset1 < dOffset2 ? -1 : ((GRADIENTSTOP*)arg1)->nIndex - ((GRADIENTSTOP*)arg2)->nIndex;
  535. };
  536. void CXTPMarkupLinearGradientBrush::FillRect(CXTPMarkupDrawingContext* pDC , CRect rc)
  537. {
  538. HDC hDC = pDC->GetSafeHdc();
  539. int cx = rc.Width();
  540. int cy = rc.Height();
  541. if (m_pGradientStops->GetCount() == 0)
  542. return;
  543. if (cx <= 0 || cy <= 0)
  544. return;
  545. if (m_pGradientStops->GetCount() == 1)
  546. {
  547. COLORREF clr = m_pGradientStops->GetItem(0)->GetColor();
  548. COLORREF clrOld = ::SetBkColor(hDC, clr);
  549. ::ExtTextOut(hDC, 0, 0, ETO_OPAQUE, rc, NULL, 0, NULL);
  550. ::SetBkColor(hDC, clrOld);
  551. return;
  552. }
  553. CXTPMarkupPoint ptStartPoint(0, 0);
  554. if (GetValue(m_pStartPointProperty)) ptStartPoint =  *MARKUP_STATICCAST(CXTPMarkupPoint, GetValue(m_pStartPointProperty));
  555. CXTPMarkupPoint ptEndPoint(1, 1);
  556. if (GetValue(m_pEndPointProperty)) ptEndPoint =  *MARKUP_STATICCAST(CXTPMarkupPoint, GetValue(m_pEndPointProperty));
  557. ptStartPoint.x *= cx;
  558. ptStartPoint.y *= cy;
  559. ptEndPoint.x *= cx;
  560. ptEndPoint.y *= cy;
  561. BOOL bHorizontal = ptStartPoint.y == ptEndPoint.y;
  562. BOOL bVertical = ptStartPoint.x == ptEndPoint.x;
  563. if (bHorizontal && bVertical)
  564. return;
  565. CRect rcClipBox = pDC->GetClipBox();
  566. if (pDC->IsPrinting())
  567. rcClipBox.InflateRect(1, 1);
  568. rcClipBox.OffsetRect(-rc.TopLeft());
  569. if (!rcClipBox.IntersectRect(&rcClipBox, CRect(0, 0, cx, cy)))
  570. return;
  571. LPDWORD lpBits;
  572. HBITMAP hBitmap = CXTPImageManager::Create32BPPDIBSection(0, cx, cy, (LPBYTE*)&lpBits);
  573. int nCount = m_pGradientStops->GetCount();
  574. GRADIENTSTOP* pStops = new GRADIENTSTOP[nCount];
  575. for (int i = 0; i < nCount; i++)
  576. {
  577. CXTPMarkupGradientStop* pItem = m_pGradientStops->GetItem(i);
  578. COLORREF clr = pItem->GetColor();
  579. pStops[i].clr.rgbRed = GetRValue(clr);
  580. pStops[i].clr.rgbGreen = GetGValue(clr);
  581. pStops[i].clr.rgbBlue = GetBValue(clr);
  582. pStops[i].clr.rgbReserved = 0;
  583. pStops[i].dOffset = pItem->GetOffset();
  584. pStops[i].nIndex = i;
  585. }
  586. GRADIENTSTOP *pStopFirst = pStops, *pStopLast = pStops + nCount - 1, *pStop;
  587. qsort(pStopFirst, nCount, sizeof(GRADIENTSTOP), _GradientStopCompare);
  588. for (pStop = pStopFirst + 1; pStop <= pStopLast; pStop++)
  589. {
  590. pStop->dDiff = pStop->dOffset - (pStop - 1)->dOffset;
  591. }
  592. CXTPMarkupPoint ptCenter((double)cx / 2, (double)cy /2);
  593. double len = sqrt(pow(ptStartPoint.x - ptEndPoint.x, 2) + pow(ptStartPoint.y - ptEndPoint.y, 2));
  594. double cosA = (ptEndPoint.x - ptStartPoint.x) / len;
  595. double sinA = (ptEndPoint.y - ptStartPoint.y) / len;
  596. double dDiff = - ptCenter.x * cosA  - ptCenter.y * sinA + ptCenter.x;
  597. double dStart = ptStartPoint.x * cosA + ptStartPoint.y * sinA + dDiff;
  598. double dEnd = ptEndPoint.x * cosA + ptEndPoint.y * sinA + dDiff;
  599. LPDWORD lpPixel = lpBits;
  600. double fDist = 1.0 / (dEnd - dStart);
  601. cosA = cosA * fDist;
  602. sinA = sinA * fDist;
  603. dDiff = (dDiff - dStart) * fDist;
  604. if (bVertical)
  605. {
  606. lpPixel += (cy - rcClipBox.bottom) * cx;
  607. for (int y = (cy - rcClipBox.bottom); y < (cy - rcClipBox.top); y++)
  608. {
  609. double fAmount = double(cy - y) * sinA + dDiff;
  610. DWORD dwPixel = 0;
  611. if (fAmount <= pStopFirst->dOffset)
  612. {
  613. dwPixel =  *((LPDWORD)&pStopFirst->clr);
  614. }
  615. else if(fAmount >= pStopLast->dOffset)
  616. {
  617. dwPixel =  *((LPDWORD)&pStopLast->clr);
  618. }
  619. else for (pStop = pStopFirst + 1; pStop <= pStopLast; pStop++)
  620. {
  621. if (fAmount < pStop->dOffset && pStop->dDiff != 0)
  622. {
  623. const RGBQUAD& clrFrom = (pStop - 1)->clr;
  624. const RGBQUAD& clrTo = pStop->clr;
  625. double fAmountA = (pStop->dOffset - fAmount) / pStop->dDiff;
  626. double fAmountB = (1.0 - fAmountA);
  627. ((LPBYTE)&dwPixel)[2] = (BYTE)(clrFrom.rgbRed * fAmountA + clrTo.rgbRed * fAmountB);
  628. ((LPBYTE)&dwPixel)[1] = (BYTE)(clrFrom.rgbGreen * fAmountA + clrTo.rgbGreen * fAmountB);
  629. ((LPBYTE)&dwPixel)[0] = (BYTE)(clrFrom.rgbBlue * fAmountA + clrTo.rgbBlue * fAmountB);
  630. break;
  631. }
  632. }
  633. for (int x = 0; x < cx; x++)
  634. {
  635. *lpPixel = dwPixel;
  636. lpPixel++;
  637. }
  638. }
  639. }
  640. else if (bHorizontal)
  641. {
  642. dDiff += double(cy) * sinA;
  643. lpPixel += rcClipBox.left;
  644. for (int x = rcClipBox.left; x < rcClipBox.right; x++)
  645. {
  646. double fAmount = (double)x * cosA + dDiff;
  647. if (fAmount <= pStopFirst->dOffset)
  648. {
  649. *lpPixel =  *((LPDWORD)&pStopFirst->clr);
  650. }
  651. else if(fAmount >= pStopLast->dOffset)
  652. {
  653. *lpPixel =  *((LPDWORD)&pStopLast->clr);
  654. }
  655. else for (pStop = pStopFirst + 1; pStop <= pStopLast; pStop++)
  656. {
  657. if (fAmount < pStop->dOffset && pStop->dDiff != 0)
  658. {
  659. const RGBQUAD& clrFrom = (pStop - 1)->clr;
  660. const RGBQUAD& clrTo = pStop->clr;
  661. double fAmountA = (pStop->dOffset - fAmount) / pStop->dDiff;
  662. double fAmountB = (1.0 - fAmountA);
  663. ((LPBYTE)lpPixel)[2] = (BYTE)(clrFrom.rgbRed * fAmountA + clrTo.rgbRed * fAmountB);
  664. ((LPBYTE)lpPixel)[1] = (BYTE)(clrFrom.rgbGreen * fAmountA + clrTo.rgbGreen * fAmountB);
  665. ((LPBYTE)lpPixel)[0] = (BYTE)(clrFrom.rgbBlue * fAmountA + clrTo.rgbBlue * fAmountB);
  666. break;
  667. }
  668. }
  669. lpPixel++;
  670. }
  671. lpPixel += (cx - rcClipBox.right);
  672. int y = max(1, cy - rcClipBox.bottom);
  673. if (y > 1)
  674. {
  675. lpPixel += cx * (cy - rcClipBox.bottom - 1);
  676. }
  677. for (; y < (cy - rcClipBox.top); y++)
  678. {
  679. memcpy(lpPixel, lpBits, sizeof(DWORD) * cx);
  680. lpPixel += cx;
  681. }
  682. }
  683. else
  684. {
  685. lpPixel += (cy - rcClipBox.bottom) * cx;
  686. for (int y = (cy - rcClipBox.bottom); y < (cy - rcClipBox.top); y++)
  687. {
  688. lpPixel += rcClipBox.left;
  689. for (int x = rcClipBox.left; x < rcClipBox.right; x++)
  690. {
  691. double fAmount = (double)x * cosA + double(cy - y) * sinA + dDiff;
  692. if (fAmount <= pStopFirst->dOffset)
  693. {
  694. *lpPixel =  *((LPDWORD)&pStopFirst->clr);
  695. }
  696. else if(fAmount >= pStopLast->dOffset)
  697. {
  698. *lpPixel =  *((LPDWORD)&pStopLast->clr);
  699. }
  700. else for (pStop = pStopFirst + 1; pStop <= pStopLast; pStop++)
  701. {
  702. if (fAmount < pStop->dOffset && pStop->dDiff != 0)
  703. {
  704. const RGBQUAD& clrFrom = (pStop - 1)->clr;
  705. const RGBQUAD& clrTo = pStop->clr;
  706. double fAmountA = (pStop->dOffset - fAmount) / pStop->dDiff;
  707. double fAmountB = (1.0 - fAmountA);
  708. ((LPBYTE)lpPixel)[2] = (BYTE)(clrFrom.rgbRed * fAmountA + clrTo.rgbRed * fAmountB);
  709. ((LPBYTE)lpPixel)[1] = (BYTE)(clrFrom.rgbGreen * fAmountA + clrTo.rgbGreen * fAmountB);
  710. ((LPBYTE)lpPixel)[0] = (BYTE)(clrFrom.rgbBlue * fAmountA + clrTo.rgbBlue * fAmountB);
  711. break;
  712. }
  713. }
  714. lpPixel++;
  715. }
  716. lpPixel += (cx - rcClipBox.right);
  717. }
  718. }
  719. HDC hBitmapDC = ::CreateCompatibleDC(hDC);
  720. HBITMAP hOldBitmap = (HBITMAP)SelectObject(hBitmapDC, hBitmap);
  721. BitBlt(hDC, rc.left + rcClipBox.left, rc.top + rcClipBox.top, rcClipBox.Width(), rcClipBox.Height(), hBitmapDC, rcClipBox.left, rcClipBox.top, SRCCOPY);
  722. SelectObject(hBitmapDC, hOldBitmap);
  723. DeleteDC(hBitmapDC);
  724. DeleteObject(hBitmap);
  725. delete[] pStops;
  726. }