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

对话框与窗口

开发平台:

Visual C++

  1. // XTPMarkupTextBlock.cpp: implementation of the CXTPMarkupTextBlock 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 "XTPMarkupTextBlock.h"
  22. #include "XTPMarkupDrawingContext.h"
  23. #include "XTPMarkupInline.h"
  24. #include "XTPMarkupBuilder.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. struct CXTPMarkupTextBlock::CLinePart
  32. {
  33. CLinePart(CXTPMarkupInline* pInline, POSITION pos)
  34. {
  35. ZeroMemory(this, sizeof(CLinePart));
  36. this->pInline = pInline;
  37. this->posStart = pos;
  38. this->posEnd = pos;
  39. pInline->AddRef();
  40. }
  41. ~CLinePart()
  42. {
  43. pInline->Release();
  44. }
  45. void Calculate(CLineIterator& li);
  46. CXTPMarkupInline* pInline;
  47. POSITION posStart;
  48. POSITION posEnd;
  49. POINT ptTopLeft;
  50. POINT ptOffset;
  51. CLine* pLine;
  52. SIZE size;
  53. int nBaseline;
  54. CLinePart* m_pNextChain;
  55. };
  56. class CXTPMarkupTextBlock::CLinePartList : public CXTPMarkupTypedSimpleStack<CLinePart>
  57. {
  58. };
  59. struct CXTPMarkupTextBlock::CLine
  60. {
  61. public:
  62. CLine()
  63. {
  64. m_nWidth = m_nHeight = m_nBaseline = 0;
  65. m_pNextChain = NULL;
  66. }
  67. ~CLine()
  68. {
  69. CLinePart* pos = m_arrParts.GetHead();
  70. while (pos)
  71. {
  72. CLinePart* posDelete = pos;
  73. pos = pos->m_pNextChain;
  74. delete posDelete;
  75. }
  76. m_arrParts.RemoveAll();
  77. }
  78. public:
  79. BOOL IsEmpty() const
  80. {
  81. return m_arrParts.IsEmpty();
  82. }
  83. CLinePartList m_arrParts;
  84. int m_nWidth;
  85. int m_nHeight;
  86. int m_nBaseline;
  87. CLine* m_pNextChain;
  88. };
  89. class CXTPMarkupTextBlock::CLineList : public CXTPMarkupTypedSimpleStack<CLine>
  90. {
  91. };
  92. struct CXTPMarkupTextBlock::CLineIterator
  93. {
  94. CLineIterator()
  95. {
  96. x = y = nMaxWidth = 0;
  97. pLine = NULL;
  98. pLinePart = NULL;
  99. }
  100. int x;
  101. int y;
  102. int nMaxWidth;
  103. CLine* pLine;
  104. CLinePart* pLinePart;
  105. CLinePartList arrStack;
  106. CXTPMarkupDrawingContext* pDC;
  107. BOOL bTextWrapping;
  108. XTPMarkupTextTrimming bTextTrimming;
  109. };
  110. //////////////////////////////////////////////////////////////////////
  111. // Construction/Destruction
  112. //////////////////////////////////////////////////////////////////////
  113. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pBackgroundProperty = NULL;
  114. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pForegroundProperty = NULL;
  115. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pFontSizeProperty = NULL;
  116. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pFontWeightProperty = NULL;
  117. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pFontFamilyProperty = NULL;
  118. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pFontStyleProperty = NULL;
  119. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pTextDecorationsProperty = NULL;
  120. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pTextWrappingProperty = NULL;
  121. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pTextTrimmingProperty = NULL;
  122. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pTextAlignmentProperty = NULL;
  123. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pPaddingProperty = NULL;
  124. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pTextProperty = NULL;
  125. CXTPMarkupDependencyProperty* CXTPMarkupTextBlock::m_pFontQualityProperty = NULL;
  126. IMPLEMENT_MARKUPCLASS(L"TextBlock", CXTPMarkupTextBlock, CXTPMarkupFrameworkElement)
  127. void CXTPMarkupTextBlock::RegisterMarkupClass()
  128. {
  129. CXTPMarkupTextElement::RegisterType();
  130. m_pBackgroundProperty =
  131. CXTPMarkupTextElement::m_pBackgroundProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  132. m_pForegroundProperty =
  133. CXTPMarkupTextElement::m_pForegroundProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  134. m_pFontSizeProperty =
  135. CXTPMarkupTextElement::m_pFontSizeProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  136. m_pFontWeightProperty =
  137. CXTPMarkupTextElement::m_pFontWeightProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  138. m_pFontQualityProperty =
  139. CXTPMarkupTextElement::m_pFontQualityProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  140. m_pFontFamilyProperty =
  141. CXTPMarkupTextElement::m_pFontFamilyProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  142. m_pFontStyleProperty =
  143. CXTPMarkupTextElement::m_pFontStyleProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  144. m_pTextDecorationsProperty =
  145. CXTPMarkupTextElement::m_pTextDecorationsProperty->AddOwner(MARKUP_TYPE(CXTPMarkupTextBlock));
  146. m_pTextWrappingProperty =
  147. CXTPMarkupDependencyProperty::Register(L"TextWrapping", MARKUP_TYPE(CXTPMarkupEnum), MARKUP_TYPE(CXTPMarkupTextBlock),
  148. new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertTextWrapping, CXTPMarkupPropertyMetadata::flagAffectsMeasure));
  149. m_pTextTrimmingProperty =
  150. CXTPMarkupDependencyProperty::Register(L"TextTrimming", MARKUP_TYPE(CXTPMarkupEnum), MARKUP_TYPE(CXTPMarkupTextBlock),
  151. new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertTextTrimming, CXTPMarkupPropertyMetadata::flagAffectsMeasure));
  152. m_pTextAlignmentProperty =
  153. CXTPMarkupDependencyProperty::Register(L"TextAlignment", MARKUP_TYPE(CXTPMarkupEnum), MARKUP_TYPE(CXTPMarkupTextBlock),
  154. new CXTPMarkupPropertyMetadata(NULL, &CXTPMarkupBuilder::ConvertTextAlignment, CXTPMarkupPropertyMetadata::flagAffectsArrange));
  155. m_pPaddingProperty =
  156. CXTPMarkupDependencyProperty::Register(L"Padding", MARKUP_TYPE(CXTPMarkupThickness), MARKUP_TYPE(CXTPMarkupTextBlock),
  157. new CXTPMarkupPropertyMetadata(CXTPMarkupThickness::CreateValue(), CXTPMarkupPropertyMetadata::flagAffectsMeasure));
  158. m_pTextProperty =
  159. CXTPMarkupDependencyProperty::Register(L"Text", MARKUP_TYPE(CXTPMarkupString), MARKUP_TYPE(CXTPMarkupTextBlock),
  160. new CXTPMarkupPropertyMetadata(NULL, CXTPMarkupPropertyMetadata::flagAffectsMeasure));
  161. }
  162. CXTPMarkupTextBlock::CXTPMarkupTextBlock()
  163. {
  164. m_pInlines = new CXTPMarkupInlineCollection();
  165. m_pInlines->SetLogicalParent(this);
  166. m_nLastWidth = -1;
  167. m_szBlockSize = CSize(0, 0);
  168. m_pLineList = new CLineList();
  169. }
  170. CXTPMarkupTextBlock::~CXTPMarkupTextBlock()
  171. {
  172. RemoveAllLines();
  173. delete m_pLineList;
  174. if (m_pInlines)
  175. {
  176. m_pInlines->RemoveAll();
  177. m_pInlines->SetLogicalParent(NULL);
  178. MARKUP_RELEASE(m_pInlines);
  179. }
  180. }
  181. void CXTPMarkupTextBlock::SetTextAlignment(XTPMarkupTextAlignment alignment)
  182. {
  183. SetValue(m_pTextAlignmentProperty, CXTPMarkupEnum::CreateValue(alignment));
  184. }
  185. XTPMarkupTextAlignment CXTPMarkupTextBlock::GetTextAlignment() const
  186. {
  187. CXTPMarkupEnum* pAlign = MARKUP_STATICCAST(CXTPMarkupEnum, GetValue(m_pTextAlignmentProperty));
  188. return pAlign ? (XTPMarkupTextAlignment)(int)(*pAlign) : xtpMarkupTextAlignmentLeft;
  189. }
  190. CXTPMarkupBrush* CXTPMarkupTextBlock::GetBackground() const
  191. {
  192. return MARKUP_STATICCAST(CXTPMarkupBrush, GetValue(m_pBackgroundProperty));
  193. }
  194. CXTPMarkupBrush* CXTPMarkupTextBlock::GetForeground() const
  195. {
  196. return MARKUP_STATICCAST(CXTPMarkupBrush, GetValue(m_pForegroundProperty));
  197. }
  198. void CXTPMarkupTextBlock::SetBackground(CXTPMarkupBrush* brush)
  199. {
  200. SetValue(m_pBackgroundProperty, brush);
  201. }
  202. void CXTPMarkupTextBlock::SetForeground(CXTPMarkupBrush* brush)
  203. {
  204. SetValue(m_pForegroundProperty, brush);
  205. }
  206. void CXTPMarkupTextBlock::SetText(LPCWSTR lpszText)
  207. {
  208. SetValue(m_pTextProperty, CXTPMarkupString::CreateValue(lpszText));
  209. }
  210. CString CXTPMarkupTextBlock::GetText() const
  211. {
  212. if (m_pInlines->GetCount() != 1 || MARKUP_DYNAMICCAST(CXTPMarkupRun, m_pInlines->GetInline(0)) == 0)
  213. return _T("");
  214. return ((CXTPMarkupRun*)m_pInlines->GetInline(0))->GetText();
  215. }
  216. void CXTPMarkupTextBlock::OnPropertyChanged(CXTPMarkupDependencyProperty* pProperty, CXTPMarkupObject* pOldValue, CXTPMarkupObject* pNewValue)
  217. {
  218. if (pProperty == m_pTextProperty)
  219. {
  220. ASSERT(m_pMarkupContext);
  221. m_pInlines->RemoveAll();
  222. CXTPMarkupRun* pRun = MARKUP_CREATE(CXTPMarkupRun, m_pMarkupContext);
  223. pRun->SetText(((CXTPMarkupString*)pNewValue));
  224. m_pInlines->Add(pRun);
  225. MARKUP_ADDREF(pNewValue);
  226. }
  227. CXTPMarkupFrameworkElement::OnPropertyChanged(pProperty, pOldValue  , pNewValue);
  228. }
  229. void CXTPMarkupTextBlock::SetFontSize(int nFontSize)
  230. {
  231. SetValue(m_pFontSizeProperty, new CXTPMarkupInt(nFontSize));
  232. }
  233. int CXTPMarkupTextBlock::GetFontSize() const
  234. {
  235. CXTPMarkupInt* pFontSize = MARKUP_STATICCAST(CXTPMarkupInt, GetValue(m_pFontSizeProperty));
  236. if (!pFontSize)
  237. return -12;
  238. return *pFontSize;
  239. }
  240. void CXTPMarkupTextBlock::SetFontWeight(int nFontWeight)
  241. {
  242. SetValue(m_pFontWeightProperty, CXTPMarkupEnum::CreateValue(nFontWeight));
  243. }
  244. int CXTPMarkupTextBlock::GetFontWeight() const
  245. {
  246. CXTPMarkupEnum* pFontWeigh = MARKUP_STATICCAST(CXTPMarkupEnum, GetValue(m_pFontWeightProperty));
  247. if (!pFontWeigh)
  248. return FW_NORMAL;
  249. return *pFontWeigh;
  250. }
  251. void CXTPMarkupTextBlock::SetFontStyle(int nFontStyle)
  252. {
  253. SetValue(m_pFontStyleProperty, CXTPMarkupEnum::CreateValue(nFontStyle));
  254. }
  255. int CXTPMarkupTextBlock::GetFontStyle() const
  256. {
  257. CXTPMarkupEnum* pFontStyle = MARKUP_STATICCAST(CXTPMarkupEnum, GetValue(m_pFontStyleProperty));
  258. if (!pFontStyle)
  259. return 0;
  260. return *pFontStyle;
  261. }
  262. void CXTPMarkupTextBlock::SetTextDecorations(int nTextDecorations)
  263. {
  264. SetValue(m_pTextDecorationsProperty, CXTPMarkupEnum::CreateValue(nTextDecorations));
  265. }
  266. int CXTPMarkupTextBlock::GetTextDecorations() const
  267. {
  268. CXTPMarkupEnum* pTextDecorations = MARKUP_STATICCAST(CXTPMarkupEnum, GetValue(m_pTextDecorationsProperty));
  269. if (!pTextDecorations)
  270. return 0;
  271. return *pTextDecorations;
  272. }
  273. void CXTPMarkupTextBlock::SetFontFamily(LPCWSTR lpszFontFamily)
  274. {
  275. SetValue(m_pFontFamilyProperty, CXTPMarkupString::CreateValue(lpszFontFamily));
  276. }
  277. LPCWSTR CXTPMarkupTextBlock::GetFontFamily() const
  278. {
  279. CXTPMarkupString* pFontFamily = MARKUP_STATICCAST(CXTPMarkupString, GetValue(m_pFontFamilyProperty));
  280. if (!pFontFamily)
  281. return NULL;
  282. return *pFontFamily;
  283. }
  284. CXTPMarkupInline* CXTPMarkupTextBlock::GetFirstInline() const
  285. {
  286. return m_pInlines->GetCount() > 0 ? m_pInlines->GetInline(0)->GetFirstInline() : NULL;
  287. }
  288. void CXTPMarkupTextBlock::RemoveAllLines()
  289. {
  290. CLine* pLine = m_pLineList->GetHead();
  291. while (pLine)
  292. {
  293. CLine* pLineDelete = pLine;
  294. pLine = pLine->m_pNextChain;
  295. delete pLineDelete;
  296. }
  297. m_pLineList->RemoveAll();
  298. }
  299. void CXTPMarkupTextBlock::TrimLine(CLineIterator& li, int nWidth)
  300. {
  301. CXTPMarkupRun* pRunEllipsis = MARKUP_CREATE(CXTPMarkupRun, m_pMarkupContext);
  302. pRunEllipsis->SetLogicalParent(this);
  303. pRunEllipsis->SetText(L"...");
  304. CLinePart* pPartEllipsis = new CLinePart(pRunEllipsis, pRunEllipsis->GetContentStartPosition());
  305. pRunEllipsis->GetContentNextPosition(pPartEllipsis->posEnd);
  306. pRunEllipsis->GetContentNextPosition(pPartEllipsis->posEnd);
  307. pRunEllipsis->GetContentNextPosition(pPartEllipsis->posEnd);
  308. pPartEllipsis->pInline->PrepareMeasure(li.pDC);
  309. pPartEllipsis->Calculate(li);
  310. nWidth -= pPartEllipsis->size.cx;
  311. int x = 0;
  312. CLinePart* pPart = li.pLine->m_arrParts.GetHead();
  313. while (pPart)
  314. {
  315. if (x + pPart->size.cx > nWidth)
  316. {
  317. CXTPMarkupInline* pInline = pPart->pInline;
  318. pPart->posEnd = pPart->posStart;
  319. POSITION posChar = pPart->posEnd, posWord = (x == 0 ? NULL : pPart->posEnd);
  320. while (pPart->posEnd != MARKUP_POSITION_EOF)
  321. {
  322. pPart->Calculate(li);
  323. if (x + pPart->size.cx > nWidth)
  324. break;
  325. posChar = pPart->posEnd;
  326. if (li.bTextTrimming == xtpMarkupTextTrimmingWordEllipsis && pInline->IsWordBreakPosition(pPart->posEnd))
  327. posWord = posChar;
  328. pInline->GetContentNextPosition(pPart->posEnd);
  329. }
  330. pPart->posEnd = posWord && li.bTextTrimming == xtpMarkupTextTrimmingWordEllipsis ? posWord : posChar;
  331. pPart->Calculate(li);
  332. x += pPart->size.cx;
  333. break;
  334. }
  335. x += pPart->size.cx;
  336. pPart = pPart->m_pNextChain;
  337. }
  338. if (pPart)
  339. {
  340. while (pPart->m_pNextChain)
  341. {
  342. CLinePart* pNextChain = pPart->m_pNextChain;
  343. li.pLine->m_arrParts.Remove(pNextChain);
  344. delete pNextChain;
  345. }
  346. }
  347. li.pLine->m_arrParts.AddTail(pPartEllipsis);
  348. pPartEllipsis->ptTopLeft = CPoint(x, li.y);
  349. pRunEllipsis->Release();
  350. }
  351. void CXTPMarkupTextBlock::CloseLine(CLineIterator& li, int nWidth)
  352. {
  353. if (!li.pLine->m_arrParts.IsEmpty())
  354. {
  355. ASSERT(li.pLine->m_nHeight == 0);
  356. if (li.bTextTrimming != xtpMarkupTextTrimmingNone && li.x > nWidth)
  357. {
  358. TrimLine(li, nWidth);
  359. }
  360. CLinePart* pPart = li.pLine->m_arrParts.GetHead();
  361. while (pPart)
  362. {
  363. li.pLine->m_nWidth += pPart->size.cx;
  364. li.pLine->m_nBaseline = max(li.pLine->m_nBaseline, pPart->nBaseline);
  365. pPart = pPart->m_pNextChain;
  366. }
  367. pPart = li.pLine->m_arrParts.GetHead();
  368. while (pPart)
  369. {
  370. li.pLine->m_nHeight = max(li.pLine->m_nHeight, pPart->size.cy - pPart->nBaseline + li.pLine->m_nBaseline);
  371. pPart = pPart->m_pNextChain;
  372. }
  373. li.nMaxWidth = max(li.nMaxWidth, li.pLine->m_nWidth);
  374. li.x = 0;
  375. li.y += li.pLine->m_nHeight;
  376. m_pLineList->AddTail(li.pLine);
  377. li.pLine = new CLine();
  378. }
  379. }
  380. void CXTPMarkupTextBlock::PushLinePart(CLineIterator& li, int nWidth, BOOL bAddToStack)
  381. {
  382. if (bAddToStack && li.pLinePart && li.pLinePart->posStart != li.pLinePart->posEnd)
  383. {
  384. CLinePart* pLinePart = li.pLinePart;
  385. li.pLinePart = new CLinePart(pLinePart->pInline, pLinePart->posEnd);
  386. li.arrStack.AddTail(pLinePart);
  387. }
  388. while (!li.arrStack.IsEmpty())
  389. {
  390. if (li.bTextWrapping && li.x > 0 && li.x + GetStackWidth(li) > nWidth)
  391. {
  392. if (!bAddToStack)
  393. {
  394. break;
  395. }
  396. CloseLine(li, nWidth);
  397. }
  398. CLinePart* pPart = li.arrStack.RemoveHead();
  399. if (li.x == 0 && li.y > 0 && pPart->pInline->IsWhiteSpacePosition(pPart->posStart))
  400. {
  401. while (pPart->posStart != pPart->posEnd && pPart->pInline->IsWhiteSpacePosition(pPart->posStart))
  402. {
  403. pPart->pInline->GetContentNextPosition(pPart->posStart);
  404. }
  405. if (pPart->posStart == pPart->posEnd)
  406. {
  407. delete pPart;
  408. continue;
  409. }
  410. pPart->size = pPart->pInline->Measure(li.pDC, pPart->posStart, pPart->posEnd);
  411. }
  412. CLinePart* pPartLast = !li.pLine->m_arrParts.IsEmpty() ? li.pLine->m_arrParts.GetTail() : NULL;
  413. if (pPartLast && pPartLast->posEnd == pPart->posStart && pPart->pInline == pPartLast->pInline && pPartLast->pInline)
  414. {
  415. ASSERT(pPartLast->size.cy == pPart->size.cy);
  416. pPartLast->posEnd = pPart->posEnd;
  417. li.x -= pPartLast->size.cx;
  418. pPartLast->size = pPartLast->pInline->Measure(li.pDC, pPartLast->posStart, pPartLast->posEnd);
  419. li.x += pPartLast->size.cx;
  420. delete pPart;
  421. }
  422. else
  423. {
  424. pPart->ptTopLeft = CPoint(li.x, li.y);
  425. pPart->pLine = li.pLine;
  426. li.pLine->m_arrParts.AddTail(pPart);
  427. li.x += pPart->size.cx;
  428. }
  429. }
  430. }
  431. void CXTPMarkupTextBlock::CLinePart::Calculate(CLineIterator& li)
  432. {
  433. size = pInline->Measure(li.pDC, posStart, posEnd);
  434. nBaseline = pInline->GetBaseline();
  435. }
  436. int CXTPMarkupTextBlock::GetStackWidth(CLineIterator& li) const
  437. {
  438. int nStackWidth = 0;
  439. for (CLinePart* part = li.arrStack.GetHead(); part != NULL; part = part->m_pNextChain)
  440. {
  441. nStackWidth += part->size.cx;
  442. }
  443. return nStackWidth;
  444. }
  445. void CXTPMarkupTextBlock::CalculateLines(CXTPMarkupDrawingContext* pDC, int nWidth)
  446. {
  447. CLineIterator li;
  448. li.bTextWrapping = GetTextWrapping();
  449. li.bTextTrimming = li.bTextWrapping ? xtpMarkupTextTrimmingNone : GetTextTrimming();
  450. if (((m_nLastWidth == nWidth) || (!li.bTextWrapping && !li.bTextTrimming && m_nLastWidth != -1)) && !pDC->IsPrinting())
  451. return;
  452. m_nLastWidth = nWidth;
  453. RemoveAllLines();
  454. li.pLine = new CLine();
  455. li.pDC = pDC;
  456. CXTPMarkupInline* pInline = GetFirstInline();
  457. while (pInline)
  458. {
  459. pInline->PrepareMeasure(li.pDC);
  460. POSITION pos = pInline->GetContentStartPosition();
  461. li.pLinePart = new CLinePart(pInline, pos);
  462. while (pos != MARKUP_POSITION_EOF)
  463. {
  464. li.pLinePart->posEnd = pos;
  465. if (li.bTextWrapping && pInline->IsWordBreakPosition(pos))
  466. {
  467. li.pLinePart->Calculate(li);
  468. PushLinePart(li, nWidth);
  469. }
  470. if (pInline->IsLineBreakPosition(pos))
  471. {
  472. pInline->GetContentNextPosition(pos);
  473. if (li.pLine->m_arrParts.IsEmpty())
  474. {
  475. if (li.pLinePart->posEnd == li.pLinePart->posStart && li.arrStack.IsEmpty())
  476. li.pLinePart->posEnd = pos;
  477. li.pLinePart->Calculate(li);
  478. PushLinePart(li, nWidth);
  479. }
  480. CloseLine(li, nWidth);
  481. li.pLinePart->posStart = pos;
  482. continue;
  483. }
  484. pInline->GetContentNextPosition(pos);
  485. }
  486. if (li.pLinePart->posStart == li.pLinePart->posEnd)
  487. {
  488. delete li.pLinePart;
  489. }
  490. else
  491. {
  492. li.pLinePart->Calculate(li);
  493. li.arrStack.AddTail(li.pLinePart);
  494. }
  495. li.pLinePart = NULL;
  496. pInline = pInline->GetNextInline();
  497. }
  498. PushLinePart(li, nWidth);
  499. CloseLine(li, nWidth);
  500. delete li.pLine;
  501. ASSERT(!li.pLinePart);
  502. ASSERT(li.arrStack.IsEmpty());
  503. if (pDC->IsPrinting())
  504. m_nLastWidth = -1;
  505. m_szBlockSize = CSize(li.nMaxWidth, li.y);
  506. };
  507. void CXTPMarkupTextBlock::InvalidateMeasureOverride(CXTPMarkupDrawingContext* pDC)
  508. {
  509. m_nLastWidth = -1;
  510. CXTPMarkupFrameworkElement::InvalidateMeasureOverride(pDC);
  511. }
  512. CSize CXTPMarkupTextBlock::MeasureOverride(CXTPMarkupDrawingContext* pDC, CSize szAvailableSize)
  513. {
  514. CSize size3 = GetPadding()->Size();
  515. CSize availableSize(max(0, szAvailableSize.cx - size3.cx), max(0, szAvailableSize.cy - size3.cy));
  516. CalculateLines(pDC, availableSize.cx);
  517. return CSize(m_szBlockSize.cx + size3.cx, m_szBlockSize.cy + size3.cy);
  518. }
  519. CSize CXTPMarkupTextBlock::ArrangeOverride(CSize szFinalSize)
  520. {
  521. CXTPMarkupThickness* pPadding = GetPadding();
  522. XTPMarkupTextAlignment textAlignment = GetTextAlignment();
  523. for (CLine* pLine = m_pLineList->GetHead(); pLine != NULL; pLine = pLine->m_pNextChain)
  524. {
  525. int xOffset = textAlignment == xtpMarkupTextAlignmentRight ? szFinalSize.cx - pLine->m_nWidth :
  526. textAlignment == xtpMarkupTextAlignmentCenter ? (szFinalSize.cx - pLine->m_nWidth) / 2 : 0;
  527. for (CLinePart* part = pLine->m_arrParts.GetHead(); part != NULL; part = part->m_pNextChain)
  528. {
  529. part->ptOffset = CPoint(pPadding->left + xOffset, pPadding->top + pLine->m_nHeight - part->size.cy);
  530. XTPMarkupBaselineAlignment baseline = part->pInline->GetBaselineAlignment();
  531. switch (baseline)
  532. {
  533. case xtpMarkupBaseline:
  534. part->ptOffset.y += part->nBaseline - pLine->m_nBaseline;
  535. break;
  536. case xtpMarkupBaselineSubscript:
  537. part->ptOffset.y += part->nBaseline - pLine->m_nBaseline / 2;
  538. break;
  539. case xtpMarkupBaselineSuperscript:
  540. part->ptOffset.y += part->size.cy - pLine->m_nHeight + pLine->m_nBaseline / 2 - part->nBaseline;
  541. break;
  542. case xtpMarkupBaselineBottom:
  543. case xtpMarkupBaselineTextBottom:
  544. break;
  545. case xtpMarkupBaselineTop:
  546. case xtpMarkupBaselineTextTop:
  547. part->ptOffset.y += part->size.cy - pLine->m_nHeight;
  548. break;
  549. case xtpMarkupBaselineCenter:
  550. part->ptOffset.y += (part->size.cy - pLine->m_nHeight) / 2;
  551. break;
  552. }
  553. CRect rc(part->ptTopLeft, part->size);
  554. rc.OffsetRect(part->ptOffset);
  555. part->pInline->Arrange(rc, part->posStart, part->posEnd);
  556. }
  557. }
  558. return szFinalSize;
  559. }
  560. void CXTPMarkupTextBlock::RenderTextDecorations(CXTPMarkupDrawingContext* pDC, CLinePart* part)
  561. {
  562. CXTPMarkupInt* pTextDecorations = (CXTPMarkupInt*)part->pInline->GetValue(CXTPMarkupTextBlock::m_pTextDecorationsProperty);
  563. if (!pTextDecorations || (int)*pTextDecorations == 0)
  564. return;
  565. CRect rc(part->ptTopLeft, part->size);
  566. rc.OffsetRect(part->ptOffset);
  567. int nTopDecoration = 0;
  568. if (*pTextDecorations == 1)
  569. nTopDecoration = rc.bottom - part->nBaseline + max(1, part->pLine->m_nBaseline / 3);
  570. else if (*pTextDecorations == 2)
  571. nTopDecoration = rc.bottom - part->nBaseline + part->pLine->m_nBaseline - (part->pLine->m_nHeight - part->pLine->m_nBaseline) / 2;
  572. CRect rcDecoration(rc.left, nTopDecoration, rc.right, nTopDecoration + max(1, part->pLine->m_nBaseline / 3));
  573. CXTPMarkupObject* pDecorationsOwner = part->pInline->GetValueSource(CXTPMarkupTextBlock::m_pTextDecorationsProperty);
  574. if (!pDecorationsOwner)
  575. {
  576. ASSERT(FALSE);
  577. return;
  578. }
  579. CXTPMarkupBrush* pDecorationsBrush = (CXTPMarkupBrush*)pDecorationsOwner->GetValue(CXTPMarkupTextBlock::m_pForegroundProperty);
  580. if (pDecorationsBrush)
  581. {
  582. pDC->DrawRectangle(pDecorationsBrush, rcDecoration);
  583. }
  584. else
  585. {
  586. CXTPMarkupSolidColorBrush brush(GetMarkupContext()->GetDefaultForeground());
  587. pDC->DrawRectangle(&brush, rcDecoration);
  588. }
  589. }
  590. void CXTPMarkupTextBlock::OnRender(CXTPMarkupDrawingContext* pDC)
  591. {
  592. CXTPMarkupBrush* pTextBackground = GetBackground();
  593. if (pTextBackground != NULL)
  594. {
  595. CRect rcRender(CPoint(0, 0), GetActualSize());
  596. pTextBackground->FillRect(pDC, rcRender);
  597. }
  598. RECT rcClipBox = pDC->GetClipBox(), rcIntersect;
  599. for (CLine* pLine = m_pLineList->GetHead(); pLine != NULL; pLine = pLine->m_pNextChain)
  600. {
  601. for (CLinePart* part = pLine->m_arrParts.GetHead(); part != NULL; part = part->m_pNextChain)
  602. {
  603. CRect rc(part->ptTopLeft, part->size);
  604. rc.OffsetRect(part->ptOffset);
  605. if (!IntersectRect(&rcIntersect, &rc, &rcClipBox))
  606. continue;
  607. CXTPMarkupBrush* pForeground = part->pInline->GetForeground();
  608. CXTPMarkupBrush* pBackground = part->pInline->GetBackground();
  609. if (pBackground != NULL && pBackground != pTextBackground)
  610. {
  611. pBackground->FillRect(pDC, rc);
  612. }
  613. ::SetTextColor(pDC->GetSafeHdc(), pForeground ? pForeground->GetHintColor() : m_pMarkupContext->GetDefaultForeground());
  614. part->pInline->Render(pDC, rc, part->posStart, part->posEnd);
  615. RenderTextDecorations(pDC, part);
  616. }
  617. }
  618. }
  619. void CXTPMarkupTextBlock::SetContentObject(CXTPMarkupBuilder* pBuilder, CXTPMarkupObject* pContent)
  620. {
  621. m_pInlines->SetContentObject(pBuilder, pContent);
  622. }
  623. BOOL CXTPMarkupTextBlock::HasContentObject() const
  624. {
  625. return m_pInlines->HasContentObject();
  626. }
  627. BOOL CXTPMarkupTextBlock::AllowWhiteSpaceContent() const
  628. {
  629. return TRUE;
  630. }
  631. CXTPMarkupInputElement* CXTPMarkupTextBlock::InputHitTestOverride(CPoint point) const
  632. {
  633. for (CLine* pLine = m_pLineList->GetHead(); pLine != NULL; pLine = pLine->m_pNextChain)
  634. {
  635. for (CLinePart* part = pLine->m_arrParts.GetHead(); part != NULL; part = part->m_pNextChain)
  636. {
  637. CRect rc(part->ptTopLeft, part->size);
  638. rc.OffsetRect(part->ptOffset);
  639. if (rc.PtInRect(point))
  640. return part->pInline->InputHitTest(point);
  641. }
  642. }
  643. return (CXTPMarkupInputElement*)this;
  644. }