1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include <algorithm> 8 9 #include "xfa/src/foxitlib.h" 10 #include "xfa/src/fxfa/src/common/xfa_common.h" 11 #include "xfa_textlayout.h" 12 #include "xfa_ffapp.h" 13 #include "xfa_ffdoc.h" 14 #include "xfa_fontmgr.h" 15 CXFA_CSSTagProvider::~CXFA_CSSTagProvider() { 16 FX_POSITION pos = m_Attributes.GetStartPosition(); 17 while (pos) { 18 CFX_WideString *pName = NULL, *pValue = NULL; 19 m_Attributes.GetNextAssoc(pos, (void*&)pName, (void*&)pValue); 20 if (pName != NULL) { 21 delete pName; 22 } 23 if (pValue != NULL) { 24 delete pValue; 25 } 26 } 27 } 28 void CXFA_CSSTagProvider::GetNextAttribute(FX_POSITION& pos, 29 CFX_WideStringC& wsAttr, 30 CFX_WideStringC& wsValue) { 31 if (pos == NULL) { 32 return; 33 } 34 CFX_WideString* pName = NULL; 35 CFX_WideString* pValue = NULL; 36 m_Attributes.GetNextAssoc(pos, (void*&)pName, (void*&)pValue); 37 wsAttr = *pName; 38 wsValue = *pValue; 39 } 40 void CXFA_CSSTagProvider::SetAttribute(const CFX_WideString& wsAttr, 41 const CFX_WideString& wsValue) { 42 CFX_WideString* pName = new CFX_WideString(); 43 CFX_WideString* pValue = new CFX_WideString(); 44 *pName = wsAttr; 45 *pValue = wsValue; 46 m_Attributes.SetAt(pName, pValue); 47 } 48 void CXFA_TextParseContext::SetDecls(const IFDE_CSSDeclaration** ppDeclArray, 49 int32_t iDeclCount) { 50 if (iDeclCount <= 0 || ppDeclArray == NULL) { 51 return; 52 } 53 m_dwMatchedDecls = iDeclCount; 54 m_ppMatchedDecls = FX_Alloc(IFDE_CSSDeclaration*, iDeclCount); 55 FX_memcpy(m_ppMatchedDecls, ppDeclArray, 56 iDeclCount * sizeof(IFDE_CSSDeclaration*)); 57 } 58 CXFA_TextParser::~CXFA_TextParser() { 59 if (m_pUASheet != NULL) { 60 m_pUASheet->Release(); 61 } 62 if (m_pSelector != NULL) { 63 m_pSelector->Release(); 64 } 65 if (m_pAllocator != NULL) { 66 m_pAllocator->Release(); 67 } 68 FX_POSITION ps = m_mapXMLNodeToParseContext.GetStartPosition(); 69 while (ps) { 70 IFDE_XMLNode* pXMLNode; 71 CXFA_TextParseContext* pParseContext; 72 m_mapXMLNodeToParseContext.GetNextAssoc(ps, pXMLNode, pParseContext); 73 if (pParseContext != NULL) { 74 FDE_DeleteWith(CXFA_TextParseContext, m_pAllocator, pParseContext); 75 } 76 } 77 m_mapXMLNodeToParseContext.RemoveAll(); 78 } 79 void CXFA_TextParser::Reset() { 80 FX_POSITION ps = m_mapXMLNodeToParseContext.GetStartPosition(); 81 while (ps) { 82 IFDE_XMLNode* pXMLNode; 83 CXFA_TextParseContext* pParseContext; 84 m_mapXMLNodeToParseContext.GetNextAssoc(ps, pXMLNode, pParseContext); 85 if (pParseContext != NULL) { 86 FDE_DeleteWith(CXFA_TextParseContext, m_pAllocator, pParseContext); 87 } 88 } 89 m_mapXMLNodeToParseContext.RemoveAll(); 90 if (m_pAllocator != NULL) { 91 m_pAllocator->Release(); 92 m_pAllocator = NULL; 93 } 94 } 95 void CXFA_TextParser::InitCSSData(IXFA_TextProvider* pTextProvider) { 96 if (pTextProvider == NULL) { 97 return; 98 } 99 if (m_pSelector == NULL) { 100 CXFA_FFDoc* pDoc = pTextProvider->GetDocNode(); 101 IFX_FontMgr* pFontMgr = pDoc->GetApp()->GetFDEFontMgr(); 102 FXSYS_assert(pFontMgr != NULL); 103 m_pSelector = IFDE_CSSStyleSelector::Create(); 104 m_pSelector->SetFontMgr(pFontMgr); 105 FX_FLOAT fFontSize = 10; 106 CXFA_Font font = pTextProvider->GetFontNode(); 107 if (font.IsExistInXML()) { 108 fFontSize = font.GetFontSize(); 109 } 110 m_pSelector->SetDefFontSize(fFontSize); 111 } 112 if (m_pUASheet == NULL) { 113 m_pUASheet = LoadDefaultSheetStyle(); 114 m_pSelector->SetStyleSheet(FDE_CSSSTYLESHEETGROUP_UserAgent, m_pUASheet); 115 m_pSelector->UpdateStyleIndex(FDE_CSSMEDIATYPE_ALL); 116 } 117 } 118 IFDE_CSSStyleSheet* CXFA_TextParser::LoadDefaultSheetStyle() { 119 static const FX_WCHAR s_pStyle[] = 120 L"html,body,ol,p,ul{display:block}" 121 L"li{display:list-item}" 122 L"ol,ul{padding-left:33px}ol{list-style-type:decimal}ol,ul{margin-top:0;" 123 L"margin-bottom:0}ul,ol{margin:1.12em 0}" 124 L"a{color:#0000ff;text-decoration:underline}b{font-weight:bolder}i{font-" 125 L"style:italic}" 126 L"sup{vertical-align:+15em;font-size:.66em}sub{vertical-align:-15em;font-" 127 L"size:.66em}"; 128 return IFDE_CSSStyleSheet::LoadFromBuffer( 129 CFX_WideString(), s_pStyle, FXSYS_wcslen(s_pStyle), FX_CODEPAGE_UTF8); 130 } 131 IFDE_CSSComputedStyle* CXFA_TextParser::CreateRootStyle( 132 IXFA_TextProvider* pTextProvider) { 133 CXFA_Font font = pTextProvider->GetFontNode(); 134 CXFA_Para para = pTextProvider->GetParaNode(); 135 IFDE_CSSComputedStyle* pStyle = m_pSelector->CreateComputedStyle(NULL); 136 IFDE_CSSFontStyle* pFontStyle = pStyle->GetFontStyles(); 137 IFDE_CSSParagraphStyle* pParaStyle = pStyle->GetParagraphStyles(); 138 FX_FLOAT fLineHeight = 0, fFontSize = 10; 139 if (para.IsExistInXML()) { 140 fLineHeight = para.GetLineHeight(); 141 FDE_CSSLENGTH indent; 142 indent.Set(FDE_CSSLENGTHUNIT_Point, para.GetTextIndent()); 143 pParaStyle->SetTextIndent(indent); 144 FDE_CSSTEXTALIGN hAlgin = FDE_CSSTEXTALIGN_Left; 145 switch (para.GetHorizontalAlign()) { 146 case XFA_ATTRIBUTEENUM_Center: 147 hAlgin = FDE_CSSTEXTALIGN_Center; 148 break; 149 case XFA_ATTRIBUTEENUM_Right: 150 hAlgin = FDE_CSSTEXTALIGN_Right; 151 break; 152 case XFA_ATTRIBUTEENUM_Justify: 153 hAlgin = FDE_CSSTEXTALIGN_Justify; 154 break; 155 case XFA_ATTRIBUTEENUM_JustifyAll: 156 hAlgin = FDE_CSSTEXTALIGN_JustifyAll; 157 break; 158 } 159 pParaStyle->SetTextAlign(hAlgin); 160 FDE_CSSRECT rtMarginWidth; 161 rtMarginWidth.left.Set(FDE_CSSLENGTHUNIT_Point, para.GetMarginLeft()); 162 rtMarginWidth.top.Set(FDE_CSSLENGTHUNIT_Point, para.GetSpaceAbove()); 163 rtMarginWidth.right.Set(FDE_CSSLENGTHUNIT_Point, para.GetMarginRight()); 164 rtMarginWidth.bottom.Set(FDE_CSSLENGTHUNIT_Point, para.GetSpaceBelow()); 165 pStyle->GetBoundaryStyles()->SetMarginWidth(rtMarginWidth); 166 } 167 if (font.IsExistInXML()) { 168 pFontStyle->SetColor(font.GetColor()); 169 pFontStyle->SetFontStyle(font.IsItalic() ? FDE_CSSFONTSTYLE_Italic 170 : FDE_CSSFONTSTYLE_Normal); 171 pFontStyle->SetFontWeight(font.IsBold() ? FXFONT_FW_BOLD 172 : FXFONT_FW_NORMAL); 173 pParaStyle->SetNumberVerticalAlign(-font.GetBaselineShift()); 174 fFontSize = font.GetFontSize(); 175 FDE_CSSLENGTH letterSpacing; 176 letterSpacing.Set(FDE_CSSLENGTHUNIT_Point, font.GetLetterSpacing()); 177 pParaStyle->SetLetterSpacing(letterSpacing); 178 FX_DWORD dwDecoration = 0; 179 if (font.GetLineThrough() > 0) { 180 dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough; 181 } 182 if (font.GetUnderline() > 1) { 183 dwDecoration |= FDE_CSSTEXTDECORATION_Double; 184 } else if (font.GetUnderline() > 0) { 185 dwDecoration |= FDE_CSSTEXTDECORATION_Underline; 186 } 187 pParaStyle->SetTextDecoration(dwDecoration); 188 } 189 pParaStyle->SetLineHeight(fLineHeight); 190 pFontStyle->SetFontSize(fFontSize); 191 return pStyle; 192 } 193 IFDE_CSSComputedStyle* CXFA_TextParser::CreateStyle( 194 IFDE_CSSComputedStyle* pParentStyle) { 195 IFDE_CSSComputedStyle* pNewStyle = 196 m_pSelector->CreateComputedStyle(pParentStyle); 197 FXSYS_assert(pNewStyle != NULL); 198 if (pParentStyle) { 199 IFDE_CSSParagraphStyle* pParaStyle = pParentStyle->GetParagraphStyles(); 200 FX_DWORD dwDecoration = pParaStyle->GetTextDecoration(); 201 FX_FLOAT fBaseLine = 0; 202 if (pParaStyle->GetVerticalAlign() == FDE_CSSVERTICALALIGN_Number) { 203 fBaseLine = pParaStyle->GetNumberVerticalAlign(); 204 } 205 pParaStyle = pNewStyle->GetParagraphStyles(); 206 pParaStyle->SetTextDecoration(dwDecoration); 207 pParaStyle->SetNumberVerticalAlign(fBaseLine); 208 IFDE_CSSBoundaryStyle* pBoundarytyle = pParentStyle->GetBoundaryStyles(); 209 const FDE_CSSRECT* pRect = pBoundarytyle->GetMarginWidth(); 210 if (pRect != NULL) { 211 pBoundarytyle = pNewStyle->GetBoundaryStyles(); 212 pBoundarytyle->SetMarginWidth(*pRect); 213 } 214 } 215 return pNewStyle; 216 } 217 IFDE_CSSComputedStyle* CXFA_TextParser::ComputeStyle( 218 IFDE_XMLNode* pXMLNode, 219 IFDE_CSSComputedStyle* pParentStyle) { 220 CXFA_TextParseContext* pContext = static_cast<CXFA_TextParseContext*>( 221 m_mapXMLNodeToParseContext.GetValueAt(pXMLNode)); 222 if (!pContext) 223 return nullptr; 224 pContext->m_pParentStyle = pParentStyle; 225 pParentStyle->AddRef(); 226 CXFA_CSSTagProvider tagProvider; 227 ParseTagInfo(pXMLNode, tagProvider); 228 if (tagProvider.m_bContent) 229 return nullptr; 230 IFDE_CSSComputedStyle* pStyle = CreateStyle(pParentStyle); 231 IFDE_CSSAccelerator* pCSSAccel = m_pSelector->InitAccelerator(); 232 pCSSAccel->OnEnterTag(&tagProvider); 233 m_pSelector->ComputeStyle(&tagProvider, pContext->GetDecls(), 234 pContext->CountDecls(), pStyle); 235 pCSSAccel->OnLeaveTag(&tagProvider); 236 return pStyle; 237 } 238 void CXFA_TextParser::DoParse(IFDE_XMLNode* pXMLContainer, 239 IXFA_TextProvider* pTextProvider) { 240 if (pXMLContainer == NULL || pTextProvider == NULL || m_pAllocator != NULL) { 241 return; 242 } 243 m_pAllocator = 244 FX_CreateAllocator(FX_ALLOCTYPE_Fixed, 32, sizeof(CXFA_CSSTagProvider)); 245 InitCSSData(pTextProvider); 246 IFDE_CSSComputedStyle* pRootStyle = CreateRootStyle(pTextProvider); 247 ParseRichText(pXMLContainer, pRootStyle); 248 pRootStyle->Release(); 249 } 250 void CXFA_TextParser::ParseRichText(IFDE_XMLNode* pXMLNode, 251 IFDE_CSSComputedStyle* pParentStyle) { 252 if (pXMLNode == NULL) { 253 return; 254 } 255 CXFA_CSSTagProvider tagProvider; 256 ParseTagInfo(pXMLNode, tagProvider); 257 if (!tagProvider.m_bTagAviliable) { 258 return; 259 } 260 IFDE_CSSComputedStyle* pNewStyle = NULL; 261 if ((tagProvider.GetTagName() != FX_WSTRC(L"body")) || 262 (tagProvider.GetTagName() != FX_WSTRC(L"html"))) { 263 CXFA_TextParseContext* pTextContext = 264 FDE_NewWith(m_pAllocator) CXFA_TextParseContext; 265 FDE_CSSDISPLAY eDisplay = FDE_CSSDISPLAY_Inline; 266 if (!tagProvider.m_bContent) { 267 pNewStyle = CreateStyle(pParentStyle); 268 IFDE_CSSAccelerator* pCSSAccel = m_pSelector->InitAccelerator(); 269 pCSSAccel->OnEnterTag(&tagProvider); 270 CFDE_CSSDeclarationArray DeclArray; 271 int32_t iMatchedDecls = 272 m_pSelector->MatchDeclarations(&tagProvider, DeclArray); 273 const IFDE_CSSDeclaration** ppMatchDecls = 274 (const IFDE_CSSDeclaration**)DeclArray.GetData(); 275 m_pSelector->ComputeStyle(&tagProvider, ppMatchDecls, iMatchedDecls, 276 pNewStyle); 277 pCSSAccel->OnLeaveTag(&tagProvider); 278 if (iMatchedDecls > 0) { 279 pTextContext->SetDecls(ppMatchDecls, iMatchedDecls); 280 } 281 eDisplay = pNewStyle->GetPositionStyles()->GetDisplay(); 282 } 283 pTextContext->SetDisplay(eDisplay); 284 m_mapXMLNodeToParseContext.SetAt(pXMLNode, pTextContext); 285 } 286 for (IFDE_XMLNode* pXMLChild = 287 pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild); 288 pXMLChild; 289 pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) { 290 ParseRichText(pXMLChild, pNewStyle); 291 } 292 if (pNewStyle != NULL) { 293 pNewStyle->Release(); 294 } 295 } 296 void CXFA_TextParser::ParseTagInfo(IFDE_XMLNode* pXMLNode, 297 CXFA_CSSTagProvider& tagProvider) { 298 static const FX_DWORD s_XFATagName[] = { 299 0x61, 0x62, 0x69, 0x70, 0x0001f714, 300 0x00022a55, 0x000239bb, 0x00025881, 0x0bd37faa, 0x0bd37fb8, 301 0xa73e3af2, 0xb182eaae, 0xdb8ac455, 302 }; 303 CFX_WideString wsName; 304 if (pXMLNode->GetType() == FDE_XMLNODE_Element) { 305 IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode; 306 pXMLElement->GetLocalTagName(wsName); 307 tagProvider.SetTagNameObj(wsName); 308 FX_DWORD dwHashCode = 309 FX_HashCode_String_GetW(wsName, wsName.GetLength(), TRUE); 310 static const int32_t s_iCount = sizeof(s_XFATagName) / sizeof(FX_DWORD); 311 CFX_DSPATemplate<FX_DWORD> lookup; 312 tagProvider.m_bTagAviliable = 313 lookup.Lookup(dwHashCode, s_XFATagName, s_iCount) > -1; 314 CFX_WideString wsValue; 315 pXMLElement->GetString(FX_WSTRC(L"style").GetPtr(), wsValue); 316 if (!wsValue.IsEmpty()) { 317 tagProvider.SetAttribute(FX_WSTRC(L"style"), wsValue); 318 } 319 } else if (pXMLNode->GetType() == FDE_XMLNODE_Text) { 320 tagProvider.m_bTagAviliable = TRUE; 321 tagProvider.m_bContent = TRUE; 322 } 323 } 324 int32_t CXFA_TextParser::GetVAlgin(IXFA_TextProvider* pTextProvider) const { 325 int32_t iAlign = XFA_ATTRIBUTEENUM_Top; 326 CXFA_Para para = pTextProvider->GetParaNode(); 327 if (para.IsExistInXML()) { 328 iAlign = para.GetVerticalAlign(); 329 } 330 return iAlign; 331 } 332 FX_FLOAT CXFA_TextParser::GetTabInterval(IFDE_CSSComputedStyle* pStyle) const { 333 CFX_WideString wsValue; 334 if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"tab-interval"), wsValue)) { 335 CXFA_Measurement ms(wsValue); 336 return ms.ToUnit(XFA_UNIT_Pt); 337 } 338 return 36; 339 } 340 int32_t CXFA_TextParser::CountTabs(IFDE_CSSComputedStyle* pStyle) const { 341 CFX_WideString wsValue; 342 if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"xfa-tab-count"), wsValue)) { 343 return wsValue.GetInteger(); 344 } 345 return 0; 346 } 347 FX_BOOL CXFA_TextParser::IsSpaceRun(IFDE_CSSComputedStyle* pStyle) const { 348 CFX_WideString wsValue; 349 if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"xfa-spacerun"), wsValue)) { 350 wsValue.MakeLower(); 351 return wsValue == FX_WSTRC(L"yes"); 352 } 353 return FALSE; 354 } 355 IFX_Font* CXFA_TextParser::GetFont(IXFA_TextProvider* pTextProvider, 356 IFDE_CSSComputedStyle* pStyle) const { 357 CFX_WideStringC wsFamily = FX_WSTRC(L"Courier"); 358 FX_DWORD dwStyle = 0; 359 CXFA_Font font = pTextProvider->GetFontNode(); 360 if (font.IsExistInXML()) { 361 font.GetTypeface(wsFamily); 362 if (font.IsBold()) { 363 dwStyle |= FX_FONTSTYLE_Bold; 364 } 365 if (font.IsItalic()) { 366 dwStyle |= FX_FONTSTYLE_Italic; 367 } 368 } 369 if (pStyle) { 370 IFDE_CSSFontStyle* pFontStyle = pStyle->GetFontStyles(); 371 int32_t iCount = pFontStyle->CountFontFamilies(); 372 if (iCount > 0) { 373 wsFamily = pFontStyle->GetFontFamily(iCount - 1); 374 } 375 dwStyle = 0; 376 if (pFontStyle->GetFontWeight() > FXFONT_FW_NORMAL) { 377 dwStyle |= FX_FONTSTYLE_Bold; 378 } 379 if (pFontStyle->GetFontStyle() == FDE_CSSFONTSTYLE_Italic) { 380 dwStyle |= FX_FONTSTYLE_Italic; 381 } 382 } 383 CXFA_FFDoc* pDoc = pTextProvider->GetDocNode(); 384 FXSYS_assert(pDoc != NULL); 385 CXFA_FontMgr* pFontMgr = pDoc->GetApp()->GetXFAFontMgr(); 386 return pFontMgr->GetFont(pDoc, wsFamily, dwStyle); 387 } 388 FX_FLOAT CXFA_TextParser::GetFontSize(IXFA_TextProvider* pTextProvider, 389 IFDE_CSSComputedStyle* pStyle) const { 390 if (pStyle != NULL) { 391 return pStyle->GetFontStyles()->GetFontSize(); 392 } 393 CXFA_Font font = pTextProvider->GetFontNode(); 394 if (font.IsExistInXML()) { 395 return font.GetFontSize(); 396 } 397 return 10; 398 } 399 int32_t CXFA_TextParser::GetHorScale(IXFA_TextProvider* pTextProvider, 400 IFDE_CSSComputedStyle* pStyle, 401 IFDE_XMLNode* pXMLNode) const { 402 if (pStyle) { 403 CFX_WideString wsValue; 404 if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-horizontal-scale"), 405 wsValue)) { 406 return wsValue.GetInteger(); 407 } 408 while (pXMLNode) { 409 CXFA_TextParseContext* pContext = static_cast<CXFA_TextParseContext*>( 410 m_mapXMLNodeToParseContext.GetValueAt(pXMLNode)); 411 if (pContext && pContext->m_pParentStyle && 412 pContext->m_pParentStyle->GetCustomStyle( 413 FX_WSTRC(L"xfa-font-horizontal-scale"), wsValue)) { 414 return wsValue.GetInteger(); 415 } 416 pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::Parent); 417 } 418 } 419 if (CXFA_Font font = pTextProvider->GetFontNode()) { 420 return static_cast<int32_t>(font.GetHorizontalScale()); 421 } 422 return 100; 423 } 424 int32_t CXFA_TextParser::GetVerScale(IXFA_TextProvider* pTextProvider, 425 IFDE_CSSComputedStyle* pStyle) const { 426 if (pStyle != NULL) { 427 CFX_WideString wsValue; 428 if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-vertical-scale"), wsValue)) { 429 return wsValue.GetInteger(); 430 } 431 } 432 if (CXFA_Font font = pTextProvider->GetFontNode()) { 433 return (int32_t)font.GetVerticalScale(); 434 } 435 return 100; 436 } 437 void CXFA_TextParser::GetUnderline(IXFA_TextProvider* pTextProvider, 438 IFDE_CSSComputedStyle* pStyle, 439 int32_t& iUnderline, 440 int32_t& iPeriod) const { 441 iUnderline = 0; 442 iPeriod = XFA_ATTRIBUTEENUM_All; 443 if (pStyle) { 444 FX_DWORD dwDecoration = pStyle->GetParagraphStyles()->GetTextDecoration(); 445 if (dwDecoration & FDE_CSSTEXTDECORATION_Double) { 446 iUnderline = 2; 447 } else if (dwDecoration & FDE_CSSTEXTDECORATION_Underline) { 448 iUnderline = 1; 449 } 450 CFX_WideString wsValue; 451 if (pStyle->GetCustomStyle(FX_WSTRC(L"underlinePeriod"), wsValue)) { 452 if (wsValue == FX_WSTRC(L"word")) { 453 iPeriod = XFA_ATTRIBUTEENUM_Word; 454 } 455 } else if (CXFA_Font font = pTextProvider->GetFontNode()) { 456 iPeriod = font.GetUnderlinePeriod(); 457 } 458 } else { 459 CXFA_Font font = pTextProvider->GetFontNode(); 460 if (font.IsExistInXML()) { 461 iUnderline = font.GetUnderline(); 462 iPeriod = font.GetUnderlinePeriod(); 463 } 464 } 465 } 466 void CXFA_TextParser::GetLinethrough(IXFA_TextProvider* pTextProvider, 467 IFDE_CSSComputedStyle* pStyle, 468 int32_t& iLinethrough) const { 469 if (pStyle) { 470 FX_DWORD dwDecoration = pStyle->GetParagraphStyles()->GetTextDecoration(); 471 iLinethrough = (dwDecoration & FDE_CSSTEXTDECORATION_LineThrough) ? 1 : 0; 472 } else { 473 CXFA_Font font = pTextProvider->GetFontNode(); 474 if (font.IsExistInXML()) { 475 iLinethrough = font.GetLineThrough(); 476 } 477 } 478 } 479 FX_ARGB CXFA_TextParser::GetColor(IXFA_TextProvider* pTextProvider, 480 IFDE_CSSComputedStyle* pStyle) const { 481 if (pStyle != NULL) { 482 return pStyle->GetFontStyles()->GetColor(); 483 } 484 if (CXFA_Font font = pTextProvider->GetFontNode()) { 485 return font.GetColor(); 486 } 487 return 0xFF000000; 488 } 489 FX_FLOAT CXFA_TextParser::GetBaseline(IXFA_TextProvider* pTextProvider, 490 IFDE_CSSComputedStyle* pStyle) const { 491 if (pStyle != NULL) { 492 IFDE_CSSParagraphStyle* pParaStyle = pStyle->GetParagraphStyles(); 493 if (pParaStyle->GetVerticalAlign() == FDE_CSSVERTICALALIGN_Number) { 494 return pParaStyle->GetNumberVerticalAlign(); 495 } 496 } else if (CXFA_Font font = pTextProvider->GetFontNode()) { 497 return font.GetBaselineShift(); 498 } 499 return 0; 500 } 501 FX_FLOAT CXFA_TextParser::GetLineHeight(IXFA_TextProvider* pTextProvider, 502 IFDE_CSSComputedStyle* pStyle, 503 FX_BOOL bFirst, 504 FX_FLOAT fVerScale) const { 505 FX_FLOAT fLineHeight = 0; 506 if (pStyle != NULL) { 507 fLineHeight = pStyle->GetParagraphStyles()->GetLineHeight(); 508 } else if (CXFA_Para para = pTextProvider->GetParaNode()) { 509 fLineHeight = para.GetLineHeight(); 510 } 511 if (bFirst) { 512 FX_FLOAT fFontSize = GetFontSize(pTextProvider, pStyle); 513 if (fLineHeight < 0.1f) { 514 fLineHeight = fFontSize; 515 } else { 516 fLineHeight = std::min(fLineHeight, fFontSize); 517 } 518 } else if (fLineHeight < 0.1f) { 519 fLineHeight = GetFontSize(pTextProvider, pStyle) * 1.2f; 520 } 521 fLineHeight *= fVerScale; 522 return fLineHeight; 523 } 524 FX_BOOL CXFA_TextParser::GetEmbbedObj(IXFA_TextProvider* pTextProvider, 525 IFDE_XMLNode* pXMLNode, 526 CFX_WideString& wsValue) { 527 wsValue.Empty(); 528 if (pXMLNode == NULL) { 529 return FALSE; 530 } 531 FX_BOOL bRet = FALSE; 532 if (pXMLNode->GetType() == FDE_XMLNODE_Element) { 533 IFDE_XMLElement* pElement = (IFDE_XMLElement*)pXMLNode; 534 CFX_WideString wsAttr; 535 pElement->GetString(FX_WSTRC(L"xfa:embed").GetPtr(), wsAttr); 536 if (wsAttr.IsEmpty()) { 537 return FALSE; 538 } 539 if (wsAttr.GetAt(0) == L'#') { 540 wsAttr.Delete(0); 541 } 542 CFX_WideString ws; 543 pElement->GetString(FX_WSTRC(L"xfa:embedType").GetPtr(), ws); 544 if (ws.IsEmpty()) { 545 ws = L"som"; 546 } else { 547 ws.MakeLower(); 548 } 549 FX_BOOL bURI = (ws == FX_WSTRC(L"uri")); 550 if (!bURI && ws != FX_WSTRC(L"som")) { 551 return FALSE; 552 } 553 ws.Empty(); 554 pElement->GetString(FX_WSTRC(L"xfa:embedMode").GetPtr(), ws); 555 if (ws.IsEmpty()) { 556 ws = L"formatted"; 557 } else { 558 ws.MakeLower(); 559 } 560 FX_BOOL bRaw = (ws == FX_WSTRC(L"raw")); 561 if (!bRaw && ws != FX_WSTRC(L"formatted")) { 562 return FALSE; 563 } 564 bRet = pTextProvider->GetEmbbedObj(bURI, bRaw, wsAttr, wsValue); 565 } 566 return bRet; 567 } 568 CXFA_TextParseContext* CXFA_TextParser::GetParseContextFromMap( 569 IFDE_XMLNode* pXMLNode) { 570 return (CXFA_TextParseContext*)m_mapXMLNodeToParseContext.GetValueAt( 571 pXMLNode); 572 } 573 enum XFA_TABSTOPSSTATUS { 574 XFA_TABSTOPSSTATUS_Error, 575 XFA_TABSTOPSSTATUS_EOS, 576 XFA_TABSTOPSSTATUS_None, 577 XFA_TABSTOPSSTATUS_Alignment, 578 XFA_TABSTOPSSTATUS_StartLeader, 579 XFA_TABSTOPSSTATUS_Leader, 580 XFA_TABSTOPSSTATUS_Location, 581 }; 582 FX_BOOL CXFA_TextParser::GetTabstops( 583 IFDE_CSSComputedStyle* pStyle, 584 CXFA_TextTabstopsContext* pTabstopContext) { 585 if (pStyle == NULL || pTabstopContext == NULL) { 586 return FALSE; 587 } 588 CFX_WideString wsValue; 589 if (!pStyle->GetCustomStyle(FX_WSTRC(L"xfa-tab-stops"), wsValue) && 590 !pStyle->GetCustomStyle(FX_WSTRC(L"tab-stops"), wsValue)) { 591 return FALSE; 592 } 593 int32_t iLength = wsValue.GetLength(); 594 const FX_WCHAR* pTabStops = wsValue; 595 int32_t iCur = 0; 596 int32_t iLast = 0; 597 CFX_WideString wsAlign; 598 XFA_TABSTOPSSTATUS eStatus = XFA_TABSTOPSSTATUS_None; 599 FX_WCHAR ch; 600 while (iCur < iLength) { 601 ch = pTabStops[iCur]; 602 switch (eStatus) { 603 case XFA_TABSTOPSSTATUS_None: 604 if (ch <= ' ') { 605 iCur++; 606 } else { 607 eStatus = XFA_TABSTOPSSTATUS_Alignment; 608 iLast = iCur; 609 } 610 break; 611 case XFA_TABSTOPSSTATUS_Alignment: 612 if (ch == ' ') { 613 wsAlign = CFX_WideStringC(pTabStops + iLast, iCur - iLast); 614 eStatus = XFA_TABSTOPSSTATUS_StartLeader; 615 iCur++; 616 while (iCur < iLength && pTabStops[iCur] <= ' ') { 617 iCur++; 618 } 619 iLast = iCur; 620 } else { 621 iCur++; 622 } 623 break; 624 case XFA_TABSTOPSSTATUS_StartLeader: 625 if (ch != 'l') { 626 eStatus = XFA_TABSTOPSSTATUS_Location; 627 } else { 628 int32_t iCount = 0; 629 while (iCur < iLength) { 630 ch = pTabStops[iCur]; 631 iCur++; 632 if (ch == '(') { 633 iCount++; 634 } else if (ch == ')') { 635 iCount--; 636 if (iCount == 0) { 637 break; 638 } 639 } 640 } 641 while (iCur < iLength && pTabStops[iCur] <= ' ') { 642 iCur++; 643 } 644 iLast = iCur; 645 eStatus = XFA_TABSTOPSSTATUS_Location; 646 } 647 break; 648 case XFA_TABSTOPSSTATUS_Location: 649 if (ch == ' ') { 650 FX_DWORD dwHashCode = 651 FX_HashCode_String_GetW(wsAlign, wsAlign.GetLength(), TRUE); 652 CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast)); 653 FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt); 654 pTabstopContext->Append(dwHashCode, fPos); 655 wsAlign.Empty(); 656 eStatus = XFA_TABSTOPSSTATUS_None; 657 } 658 iCur++; 659 break; 660 default: 661 break; 662 } 663 } 664 if (!wsAlign.IsEmpty()) { 665 FX_DWORD dwHashCode = 666 FX_HashCode_String_GetW(wsAlign, wsAlign.GetLength(), TRUE); 667 CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast)); 668 FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt); 669 pTabstopContext->Append(dwHashCode, fPos); 670 } 671 return TRUE; 672 } 673 CXFA_TextLayout::CXFA_TextLayout(IXFA_TextProvider* pTextProvider) 674 : m_bHasBlock(FALSE), 675 m_pTextProvider(pTextProvider), 676 m_pTextDataNode(nullptr), 677 m_bRichText(FALSE), 678 m_pAllocator(nullptr), 679 m_pBreak(nullptr), 680 m_pLoader(nullptr), 681 m_iLines(0), 682 m_fMaxWidth(0), 683 m_pTabstopContext(nullptr), 684 m_bBlockContinue(TRUE) { 685 FXSYS_assert(m_pTextProvider); 686 } 687 CXFA_TextLayout::~CXFA_TextLayout() { 688 m_textParser.Reset(); 689 delete m_pLoader; 690 delete m_pTabstopContext; 691 Unload(); 692 } 693 void CXFA_TextLayout::Unload() { 694 int32_t iCount = m_pieceLines.GetSize(); 695 for (int32_t i = 0; i < iCount; i++) { 696 CXFA_PieceLine* pLine = m_pieceLines.GetAt(i); 697 FDE_DeleteWith(CXFA_PieceLine, m_pAllocator, pLine); 698 } 699 m_pieceLines.RemoveAll(); 700 if (m_pBreak != NULL) { 701 m_pBreak->Release(); 702 m_pBreak = NULL; 703 } 704 if (m_pAllocator != NULL) { 705 m_pAllocator->Release(); 706 m_pAllocator = NULL; 707 } 708 } 709 const CXFA_PieceLineArray* CXFA_TextLayout::GetPieceLines() { 710 return &m_pieceLines; 711 } 712 void CXFA_TextLayout::GetTextDataNode() { 713 if (m_pTextProvider == NULL) { 714 return; 715 } 716 CXFA_Node* pNode = m_pTextProvider->GetTextNode(m_bRichText); 717 if (pNode && m_bRichText) { 718 m_textParser.Reset(); 719 } 720 m_pTextDataNode = pNode; 721 } 722 IFDE_XMLNode* CXFA_TextLayout::GetXMLContainerNode() { 723 IFDE_XMLNode* pXMLContainer = NULL; 724 if (m_bRichText) { 725 IFDE_XMLNode* pXMLRoot = m_pTextDataNode->GetXMLMappingNode(); 726 if (!pXMLRoot) { 727 return pXMLContainer; 728 } 729 for (IFDE_XMLNode* pXMLChild = 730 pXMLRoot->GetNodeItem(IFDE_XMLNode::FirstChild); 731 pXMLChild; 732 pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) { 733 if (pXMLChild->GetType() == FDE_XMLNODE_Element) { 734 IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLChild; 735 CFX_WideString wsTag; 736 pXMLElement->GetLocalTagName(wsTag); 737 if (wsTag.Equal(FX_WSTRC(L"body")) || wsTag.Equal(FX_WSTRC(L"html"))) { 738 pXMLContainer = pXMLChild; 739 break; 740 } 741 } 742 } 743 } 744 return pXMLContainer; 745 } 746 IFX_RTFBreak* CXFA_TextLayout::CreateBreak(FX_BOOL bDefault) { 747 FX_DWORD dwStyle = FX_RTFLAYOUTSTYLE_ExpandTab; 748 if (!bDefault) { 749 dwStyle |= FX_RTFLAYOUTSTYLE_Pagination; 750 } 751 IFX_RTFBreak* pBreak = IFX_RTFBreak::Create(0); 752 pBreak->SetLayoutStyles(dwStyle); 753 pBreak->SetLineBreakChar(L'\n'); 754 pBreak->SetLineBreakTolerance(1); 755 pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, NULL)); 756 pBreak->SetFontSize(m_textParser.GetFontSize(m_pTextProvider, NULL)); 757 return pBreak; 758 } 759 void CXFA_TextLayout::InitBreak(FX_FLOAT fLineWidth) { 760 CXFA_Font font = m_pTextProvider->GetFontNode(); 761 CXFA_Para para = m_pTextProvider->GetParaNode(); 762 FX_FLOAT fStart = 0; 763 FX_FLOAT fStartPos = 0; 764 if (para.IsExistInXML()) { 765 int32_t iAlign = FX_RTFLINEALIGNMENT_Left; 766 switch (para.GetHorizontalAlign()) { 767 case XFA_ATTRIBUTEENUM_Center: 768 iAlign = FX_RTFLINEALIGNMENT_Center; 769 break; 770 case XFA_ATTRIBUTEENUM_Right: 771 iAlign = FX_RTFLINEALIGNMENT_Right; 772 break; 773 case XFA_ATTRIBUTEENUM_Justify: 774 iAlign = FX_RTFLINEALIGNMENT_Justified; 775 break; 776 case XFA_ATTRIBUTEENUM_JustifyAll: 777 iAlign = FX_RTFLINEALIGNMENT_Distributed; 778 break; 779 } 780 m_pBreak->SetAlignment(iAlign); 781 fStart = para.GetMarginLeft(); 782 if (m_pTextProvider->IsCheckButtonAndAutoWidth()) { 783 if (iAlign != FX_RTFLINEALIGNMENT_Left) { 784 fLineWidth -= para.GetMarginRight(); 785 } 786 } else { 787 fLineWidth -= para.GetMarginRight(); 788 } 789 if (fLineWidth < 0) { 790 fLineWidth = fStart; 791 } 792 fStartPos = fStart; 793 FX_FLOAT fIndent = para.GetTextIndent(); 794 if (fIndent > 0) { 795 fStartPos += fIndent; 796 } 797 } 798 m_pBreak->SetLineBoundary(fStart, fLineWidth); 799 m_pBreak->SetLineStartPos(fStartPos); 800 if (font.IsExistInXML()) { 801 m_pBreak->SetHorizontalScale((int32_t)font.GetHorizontalScale()); 802 m_pBreak->SetVerticalScale((int32_t)font.GetVerticalScale()); 803 m_pBreak->SetCharSpace(font.GetLetterSpacing()); 804 } 805 FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, NULL); 806 m_pBreak->SetFontSize(fFontSize); 807 m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, NULL)); 808 m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f); 809 } 810 void CXFA_TextLayout::InitBreak(IFDE_CSSComputedStyle* pStyle, 811 FDE_CSSDISPLAY eDisplay, 812 FX_FLOAT fLineWidth, 813 IFDE_XMLNode* pXMLNode, 814 IFDE_CSSComputedStyle* pParentStyle) { 815 if (pStyle == NULL) { 816 InitBreak(fLineWidth); 817 return; 818 } 819 IFDE_CSSParagraphStyle* pParaStyle = pStyle->GetParagraphStyles(); 820 if (eDisplay == FDE_CSSDISPLAY_Block || eDisplay == FDE_CSSDISPLAY_ListItem) { 821 int32_t iAlign = FX_RTFLINEALIGNMENT_Left; 822 switch (pParaStyle->GetTextAlign()) { 823 case FDE_CSSTEXTALIGN_Right: 824 iAlign = FX_RTFLINEALIGNMENT_Right; 825 break; 826 case FDE_CSSTEXTALIGN_Center: 827 iAlign = FX_RTFLINEALIGNMENT_Center; 828 break; 829 case FDE_CSSTEXTALIGN_Justify: 830 iAlign = FX_RTFLINEALIGNMENT_Justified; 831 break; 832 case FDE_CSSTEXTALIGN_JustifyAll: 833 iAlign = FX_RTFLINEALIGNMENT_Distributed; 834 break; 835 default: 836 break; 837 } 838 m_pBreak->SetAlignment(iAlign); 839 FX_FLOAT fStart = 0; 840 const FDE_CSSRECT* pRect = pStyle->GetBoundaryStyles()->GetMarginWidth(); 841 const FDE_CSSRECT* pPaddingRect = 842 pStyle->GetBoundaryStyles()->GetPaddingWidth(); 843 if (pRect != NULL) { 844 fStart = pRect->left.GetValue(); 845 fLineWidth -= pRect->right.GetValue(); 846 if (pPaddingRect != NULL) { 847 fStart += pPaddingRect->left.GetValue(); 848 fLineWidth -= pPaddingRect->right.GetValue(); 849 } 850 if (eDisplay == FDE_CSSDISPLAY_ListItem) { 851 const FDE_CSSRECT* pParRect = 852 pParentStyle->GetBoundaryStyles()->GetMarginWidth(); 853 const FDE_CSSRECT* pParPaddingRect = 854 pParentStyle->GetBoundaryStyles()->GetPaddingWidth(); 855 if (pParRect != NULL) { 856 fStart += pParRect->left.GetValue(); 857 fLineWidth -= pParRect->right.GetValue(); 858 if (pParPaddingRect != NULL) { 859 fStart += pParPaddingRect->left.GetValue(); 860 fLineWidth -= pParPaddingRect->right.GetValue(); 861 } 862 } 863 FDE_CSSRECT pNewRect; 864 pNewRect.left.Set(FDE_CSSLENGTHUNIT_Point, fStart); 865 pNewRect.right.Set(FDE_CSSLENGTHUNIT_Point, pRect->right.GetValue()); 866 pNewRect.top.Set(FDE_CSSLENGTHUNIT_Point, pRect->top.GetValue()); 867 pNewRect.bottom.Set(FDE_CSSLENGTHUNIT_Point, pRect->bottom.GetValue()); 868 pStyle->GetBoundaryStyles()->SetMarginWidth(pNewRect); 869 } 870 } 871 m_pBreak->SetLineBoundary(fStart, fLineWidth); 872 FX_FLOAT fIndent = pParaStyle->GetTextIndent().GetValue(); 873 if (fIndent > 0) { 874 fStart += fIndent; 875 } 876 m_pBreak->SetLineStartPos(fStart); 877 m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle)); 878 if (m_pTabstopContext == NULL) { 879 m_pTabstopContext = new CXFA_TextTabstopsContext; 880 } 881 m_textParser.GetTabstops(pStyle, m_pTabstopContext); 882 for (int32_t i = 0; i < m_pTabstopContext->m_iTabCount; i++) { 883 XFA_TABSTOPS* pTab = m_pTabstopContext->m_tabstops.GetDataPtr(i); 884 m_pBreak->AddPositionedTab(pTab->fTabstops); 885 } 886 } 887 FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle); 888 m_pBreak->SetFontSize(fFontSize); 889 m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f); 890 m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, pStyle)); 891 m_pBreak->SetHorizontalScale( 892 m_textParser.GetHorScale(m_pTextProvider, pStyle, pXMLNode)); 893 m_pBreak->SetVerticalScale(m_textParser.GetVerScale(m_pTextProvider, pStyle)); 894 m_pBreak->SetCharSpace(pParaStyle->GetLetterSpacing().GetValue()); 895 } 896 int32_t CXFA_TextLayout::GetText(CFX_WideString& wsText) { 897 GetTextDataNode(); 898 wsText.Empty(); 899 if (m_bRichText) { 900 } else { 901 wsText = m_pTextDataNode->GetContent(); 902 } 903 return wsText.GetLength(); 904 } 905 FX_FLOAT CXFA_TextLayout::GetLayoutHeight() { 906 if (m_pLoader == NULL) { 907 return 0; 908 } 909 int32_t iCount = m_pLoader->m_lineHeights.GetSize(); 910 if (iCount == 0 && m_pLoader->m_fWidth > 0) { 911 CFX_SizeF szMax, szDef; 912 szMax.Set(m_pLoader->m_fWidth, m_pLoader->m_fHeight); 913 szDef.Set(0, 0); 914 m_pLoader->m_bSaveLineHeight = TRUE; 915 m_pLoader->m_fLastPos = 0; 916 CalcSize(szMax, szMax, szDef); 917 m_pLoader->m_bSaveLineHeight = FALSE; 918 return szDef.y; 919 } 920 FX_FLOAT fHeight = m_pLoader->m_fHeight; 921 if (fHeight < 0.1f) { 922 fHeight = 0; 923 for (int32_t i = 0; i < iCount; i++) { 924 fHeight += m_pLoader->m_lineHeights.ElementAt(i); 925 } 926 } 927 return fHeight; 928 } 929 FX_FLOAT CXFA_TextLayout::StartLayout(FX_FLOAT fWidth) { 930 if (m_pLoader == NULL) { 931 m_pLoader = new CXFA_LoaderContext; 932 } 933 if (fWidth < 0 || (m_pLoader->m_fWidth > -1 && 934 FXSYS_fabs(fWidth - m_pLoader->m_fWidth) > 0)) { 935 m_pLoader->m_lineHeights.RemoveAll(); 936 m_Blocks.RemoveAll(); 937 Unload(); 938 m_pLoader->m_fStartLineOffset = 0; 939 } 940 m_pLoader->m_fWidth = fWidth; 941 if (fWidth < 0) { 942 CFX_SizeF szMax, szDef; 943 szMax.Set(0, 0); 944 szDef.Set(0, 0); 945 m_pLoader->m_bSaveLineHeight = TRUE; 946 m_pLoader->m_fLastPos = 0; 947 CalcSize(szMax, szMax, szDef); 948 m_pLoader->m_bSaveLineHeight = FALSE; 949 fWidth = szDef.x; 950 } 951 return fWidth; 952 } 953 FX_BOOL CXFA_TextLayout::DoLayout(int32_t iBlockIndex, 954 FX_FLOAT& fCalcHeight, 955 FX_FLOAT fContentAreaHeight, 956 FX_FLOAT fTextHeight) { 957 if (m_pLoader == NULL) { 958 return FALSE; 959 } 960 int32_t iBlockCount = m_Blocks.GetSize(); 961 FX_FLOAT fHeight = fTextHeight; 962 if (fHeight < 0) { 963 fHeight = GetLayoutHeight(); 964 } 965 m_pLoader->m_fHeight = fHeight; 966 if (fContentAreaHeight < 0) { 967 return FALSE; 968 } 969 m_bHasBlock = TRUE; 970 if (iBlockCount == 0 && fHeight > 0) { 971 fHeight = fTextHeight - GetLayoutHeight(); 972 if (fHeight > 0) { 973 int32_t iAlign = m_textParser.GetVAlgin(m_pTextProvider); 974 if (iAlign == XFA_ATTRIBUTEENUM_Middle) { 975 fHeight /= 2.0f; 976 } else if (iAlign != XFA_ATTRIBUTEENUM_Bottom) { 977 fHeight = 0; 978 } 979 m_pLoader->m_fStartLineOffset = fHeight; 980 } 981 } 982 FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset; 983 int32_t iLineIndex = 0; 984 if (iBlockCount > 1) { 985 if (iBlockCount >= (iBlockIndex + 1) * 2) { 986 iLineIndex = m_Blocks.ElementAt(iBlockIndex * 2); 987 } else { 988 iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) + 989 m_Blocks.ElementAt(iBlockCount - 2); 990 } 991 if (m_pLoader->m_BlocksHeight.GetSize() > 0) { 992 for (int32_t i = 0; i < iBlockIndex; i++) { 993 fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1); 994 } 995 } 996 } 997 int32_t iCount = m_pLoader->m_lineHeights.GetSize(); 998 int32_t i = 0; 999 for (i = iLineIndex; i < iCount; i++) { 1000 FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i); 1001 if ((i == iLineIndex) && (fLineHeight - fContentAreaHeight > 0.001)) { 1002 fCalcHeight = 0; 1003 return TRUE; 1004 } 1005 if (fLinePos + fLineHeight - fContentAreaHeight > 0.001) { 1006 if (iBlockCount >= (iBlockIndex + 1) * 2) { 1007 m_Blocks.SetAt(iBlockIndex * 2, iLineIndex); 1008 m_Blocks.SetAt(iBlockIndex * 2 + 1, i - iLineIndex); 1009 } else { 1010 m_Blocks.Add(iLineIndex); 1011 m_Blocks.Add(i - iLineIndex); 1012 } 1013 if (i == iLineIndex) { 1014 if (fCalcHeight <= fLinePos) { 1015 if (m_pLoader->m_BlocksHeight.GetSize() > iBlockIndex * 2 && 1016 (m_pLoader->m_BlocksHeight.GetAt(iBlockIndex * 2) == 1017 iBlockIndex)) { 1018 m_pLoader->m_BlocksHeight.SetAt(iBlockIndex * 2 + 1, fCalcHeight); 1019 } else { 1020 m_pLoader->m_BlocksHeight.Add((FX_FLOAT)iBlockIndex); 1021 m_pLoader->m_BlocksHeight.Add(fCalcHeight); 1022 } 1023 } 1024 return TRUE; 1025 } 1026 fCalcHeight = fLinePos; 1027 return TRUE; 1028 } 1029 fLinePos += fLineHeight; 1030 } 1031 return FALSE; 1032 } 1033 int32_t CXFA_TextLayout::CountBlocks() const { 1034 int32_t iCount = m_Blocks.GetSize() / 2; 1035 return iCount > 0 ? iCount : 1; 1036 } 1037 FX_BOOL CXFA_TextLayout::CalcSize(const CFX_SizeF& minSize, 1038 const CFX_SizeF& maxSize, 1039 CFX_SizeF& defaultSize) { 1040 defaultSize.x = maxSize.x; 1041 if (defaultSize.x < 1) { 1042 defaultSize.x = 0xFFFF; 1043 } 1044 if (m_pBreak != NULL) { 1045 m_pBreak->Release(); 1046 } 1047 m_pBreak = CreateBreak(FALSE); 1048 FX_FLOAT fLinePos = 0; 1049 m_iLines = 0; 1050 m_fMaxWidth = 0; 1051 Loader(defaultSize, fLinePos, FALSE); 1052 if (fLinePos < 0.1f) { 1053 fLinePos = m_textParser.GetFontSize(m_pTextProvider, NULL); 1054 } 1055 if (m_pTabstopContext) { 1056 delete m_pTabstopContext; 1057 m_pTabstopContext = NULL; 1058 } 1059 defaultSize.Set(m_fMaxWidth, fLinePos); 1060 return TRUE; 1061 } 1062 FX_BOOL CXFA_TextLayout::Layout(const CFX_SizeF& size, FX_FLOAT* fHeight) { 1063 if (size.x < 1) { 1064 return FALSE; 1065 } 1066 Unload(); 1067 m_pBreak = CreateBreak(TRUE); 1068 if (m_pLoader != NULL) { 1069 m_pLoader->m_iTotalLines = -1; 1070 m_pLoader->m_iChar = 0; 1071 } 1072 m_iLines = 0; 1073 FX_FLOAT fLinePos = 0; 1074 Loader(size, fLinePos, TRUE); 1075 UpdateAlign(size.y, fLinePos); 1076 if (m_pTabstopContext) { 1077 delete m_pTabstopContext; 1078 m_pTabstopContext = NULL; 1079 } 1080 if (fHeight) { 1081 *fHeight = fLinePos; 1082 } 1083 return TRUE; 1084 } 1085 FX_BOOL CXFA_TextLayout::Layout(int32_t iBlock) { 1086 if (m_pLoader == NULL || iBlock < 0 || iBlock >= CountBlocks()) { 1087 return FALSE; 1088 } 1089 if (m_pLoader->m_fWidth < 1) { 1090 return FALSE; 1091 } 1092 m_pLoader->m_iTotalLines = -1; 1093 m_iLines = 0; 1094 FX_FLOAT fLinePos = 0; 1095 CXFA_Node* pNode = NULL; 1096 CFX_SizeF szText; 1097 szText.Set(m_pLoader->m_fWidth, m_pLoader->m_fHeight); 1098 int32_t iCount = m_Blocks.GetSize(); 1099 int32_t iBlocksHeightCount = m_pLoader->m_BlocksHeight.GetSize(); 1100 iBlocksHeightCount /= 2; 1101 if (iBlock < iBlocksHeightCount) { 1102 return TRUE; 1103 } 1104 if (iBlock == iBlocksHeightCount) { 1105 Unload(); 1106 m_pBreak = CreateBreak(TRUE); 1107 fLinePos = m_pLoader->m_fStartLineOffset; 1108 for (int32_t i = 0; i < iBlocksHeightCount; i++) { 1109 fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1); 1110 } 1111 m_pLoader->m_iChar = 0; 1112 if (iCount > 1) { 1113 m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock * 2 + 1); 1114 } 1115 Loader(szText, fLinePos, TRUE); 1116 if (iCount == 0 && m_pLoader->m_fStartLineOffset < 0.1f) { 1117 UpdateAlign(szText.y, fLinePos); 1118 } 1119 } else if (m_pTextDataNode != NULL) { 1120 iBlock *= 2; 1121 if (iBlock < iCount - 2) { 1122 m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock + 1); 1123 } 1124 m_pBreak->Reset(); 1125 if (m_bRichText) { 1126 IFDE_XMLNode* pContainerNode = GetXMLContainerNode(); 1127 if (!pContainerNode) { 1128 return TRUE; 1129 } 1130 IFDE_XMLNode* pXMLNode = m_pLoader->m_pXMLNode; 1131 if (pXMLNode == NULL) { 1132 return TRUE; 1133 } 1134 IFDE_XMLNode* pSaveXMLNode = m_pLoader->m_pXMLNode; 1135 for (; pXMLNode; 1136 pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) { 1137 FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos, 1138 m_pLoader->m_pParentStyle, TRUE); 1139 if (!bFlag) { 1140 break; 1141 } 1142 } 1143 while (pXMLNode == NULL) { 1144 pXMLNode = pSaveXMLNode->GetNodeItem(IFDE_XMLNode::Parent); 1145 if (pXMLNode == pContainerNode) { 1146 break; 1147 } 1148 FX_BOOL bFlag = 1149 LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle, 1150 TRUE, NULL, FALSE); 1151 if (!bFlag) { 1152 break; 1153 } 1154 pSaveXMLNode = pXMLNode; 1155 pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling); 1156 if (!pXMLNode) { 1157 continue; 1158 } 1159 for (; pXMLNode; 1160 pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) { 1161 FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos, 1162 m_pLoader->m_pParentStyle, TRUE); 1163 if (!bFlag) { 1164 break; 1165 } 1166 } 1167 } 1168 } else { 1169 pNode = m_pLoader->m_pNode; 1170 if (pNode == NULL) { 1171 return TRUE; 1172 } 1173 LoadText(pNode, szText, fLinePos, TRUE); 1174 } 1175 } 1176 if (iBlock == iCount) { 1177 if (m_pTabstopContext != NULL) { 1178 delete m_pTabstopContext; 1179 m_pTabstopContext = NULL; 1180 } 1181 if (m_pLoader != NULL) { 1182 delete m_pLoader; 1183 m_pLoader = NULL; 1184 } 1185 } 1186 return TRUE; 1187 } 1188 void CXFA_TextLayout::ItemBlocks(const CFX_RectF& rtText, int32_t iBlockIndex) { 1189 if (!m_pLoader) { 1190 return; 1191 } 1192 int32_t iCountHeight = m_pLoader->m_lineHeights.GetSize(); 1193 if (iCountHeight == 0) { 1194 return; 1195 } 1196 FX_BOOL bEndItem = TRUE; 1197 int32_t iBlockCount = m_Blocks.GetSize(); 1198 FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset; 1199 int32_t iLineIndex = 0; 1200 if (iBlockIndex > 0) { 1201 int32_t iBlockHeightCount = m_pLoader->m_BlocksHeight.GetSize(); 1202 iBlockHeightCount /= 2; 1203 if (iBlockHeightCount >= iBlockIndex) { 1204 for (int32_t i = 0; i < iBlockIndex; i++) { 1205 fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1); 1206 } 1207 } else { 1208 fLinePos = 0; 1209 } 1210 iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) + 1211 m_Blocks.ElementAt(iBlockCount - 2); 1212 } 1213 int32_t i = 0; 1214 for (i = iLineIndex; i < iCountHeight; i++) { 1215 FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i); 1216 if (fLinePos + fLineHeight - rtText.height > 0.001) { 1217 m_Blocks.Add(iLineIndex); 1218 m_Blocks.Add(i - iLineIndex); 1219 bEndItem = FALSE; 1220 break; 1221 } 1222 fLinePos += fLineHeight; 1223 } 1224 if (iCountHeight > 0 && (i - iLineIndex) > 0 && bEndItem) { 1225 m_Blocks.Add(iLineIndex); 1226 m_Blocks.Add(i - iLineIndex); 1227 } 1228 } 1229 FX_BOOL CXFA_TextLayout::DrawString(CFX_RenderDevice* pFxDevice, 1230 const CFX_Matrix& tmDoc2Device, 1231 const CFX_RectF& rtClip, 1232 int32_t iBlock) { 1233 IFDE_RenderDevice* pDevice = IFDE_RenderDevice::Create(pFxDevice); 1234 if (pDevice == NULL) { 1235 return FALSE; 1236 } 1237 FDE_HDEVICESTATE state = pDevice->SaveState(); 1238 pDevice->SetClipRect(rtClip); 1239 IFDE_SolidBrush* pSolidBrush = 1240 (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid); 1241 IFDE_Pen* pPen = IFDE_Pen::Create(); 1242 FXSYS_assert(pDevice != NULL && pSolidBrush != NULL && pPen != NULL); 1243 if (m_pieceLines.GetSize() == 0) { 1244 int32_t iBlockCount = CountBlocks(); 1245 for (int32_t i = 0; i < iBlockCount; i++) { 1246 Layout(i); 1247 } 1248 } 1249 FXTEXT_CHARPOS* pCharPos = NULL; 1250 int32_t iCharCount = 0; 1251 int32_t iLineStart = 0; 1252 int32_t iPieceLines = m_pieceLines.GetSize(); 1253 int32_t iCount = m_Blocks.GetSize(); 1254 if (iCount > 0) { 1255 iBlock *= 2; 1256 if (iBlock < iCount) { 1257 iLineStart = m_Blocks.ElementAt(iBlock); 1258 iPieceLines = m_Blocks.ElementAt(iBlock + 1); 1259 } else { 1260 iPieceLines = 0; 1261 } 1262 } 1263 for (int32_t i = 0; i < iPieceLines; i++) { 1264 if (i + iLineStart >= m_pieceLines.GetSize()) { 1265 break; 1266 } 1267 CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i + iLineStart); 1268 int32_t iPieces = pPieceLine->m_textPieces.GetSize(); 1269 int32_t j = 0; 1270 for (j = 0; j < iPieces; j++) { 1271 XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j); 1272 int32_t iChars = pPiece->iChars; 1273 if (iCharCount < iChars) { 1274 FX_Free(pCharPos); 1275 pCharPos = FX_Alloc(FXTEXT_CHARPOS, iChars); 1276 iCharCount = iChars; 1277 } 1278 FXSYS_memset(pCharPos, 0, iCharCount * sizeof(FXTEXT_CHARPOS)); 1279 RenderString(pDevice, pSolidBrush, pPieceLine, j, pCharPos, tmDoc2Device); 1280 } 1281 for (j = 0; j < iPieces; j++) { 1282 RenderPath(pDevice, pPen, pPieceLine, j, pCharPos, tmDoc2Device); 1283 } 1284 } 1285 pDevice->RestoreState(state); 1286 FX_Free(pCharPos); 1287 pSolidBrush->Release(); 1288 pPen->Release(); 1289 pDevice->Release(); 1290 return iPieceLines; 1291 } 1292 void CXFA_TextLayout::UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom) { 1293 fHeight -= fBottom; 1294 if (fHeight < 0.1f) { 1295 return; 1296 } 1297 switch (m_textParser.GetVAlgin(m_pTextProvider)) { 1298 case XFA_ATTRIBUTEENUM_Middle: 1299 fHeight /= 2.0f; 1300 break; 1301 case XFA_ATTRIBUTEENUM_Bottom: 1302 break; 1303 default: 1304 return; 1305 } 1306 int32_t iCount = m_pieceLines.GetSize(); 1307 for (int32_t i = 0; i < iCount; i++) { 1308 CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i); 1309 int32_t iPieces = pPieceLine->m_textPieces.GetSize(); 1310 for (int32_t j = 0; j < iPieces; j++) { 1311 XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j); 1312 CFX_RectF& rect = pPiece->rtPiece; 1313 rect.top += fHeight; 1314 } 1315 } 1316 } 1317 FX_BOOL CXFA_TextLayout::Loader(const CFX_SizeF& szText, 1318 FX_FLOAT& fLinePos, 1319 FX_BOOL bSavePieces) { 1320 if (m_pAllocator == NULL) { 1321 m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Static, 256, 0); 1322 } 1323 GetTextDataNode(); 1324 if (m_pTextDataNode == NULL) { 1325 return TRUE; 1326 } 1327 if (m_bRichText) { 1328 IFDE_XMLNode* pXMLContainer = GetXMLContainerNode(); 1329 if (pXMLContainer) { 1330 if (!m_textParser.IsParsed()) { 1331 m_textParser.DoParse(pXMLContainer, m_pTextProvider); 1332 } 1333 IFDE_CSSComputedStyle* pRootStyle = 1334 m_textParser.CreateRootStyle(m_pTextProvider); 1335 LoadRichText(pXMLContainer, szText, fLinePos, pRootStyle, bSavePieces); 1336 pRootStyle->Release(); 1337 } 1338 } else { 1339 LoadText(m_pTextDataNode, szText, fLinePos, bSavePieces); 1340 } 1341 return TRUE; 1342 } 1343 void CXFA_TextLayout::LoadText(CXFA_Node* pNode, 1344 const CFX_SizeF& szText, 1345 FX_FLOAT& fLinePos, 1346 FX_BOOL bSavePieces) { 1347 InitBreak(szText.x); 1348 CXFA_Para para = m_pTextProvider->GetParaNode(); 1349 FX_FLOAT fSpaceAbove = 0; 1350 if (para.IsExistInXML()) { 1351 fSpaceAbove = para.GetSpaceAbove(); 1352 if (fSpaceAbove < 0.1f) { 1353 fSpaceAbove = 0; 1354 } 1355 int32_t verAlign = para.GetVerticalAlign(); 1356 switch (verAlign) { 1357 case XFA_ATTRIBUTEENUM_Top: 1358 case XFA_ATTRIBUTEENUM_Middle: 1359 case XFA_ATTRIBUTEENUM_Bottom: { 1360 fLinePos += fSpaceAbove; 1361 break; 1362 } 1363 } 1364 } 1365 CFX_WideString wsText = pNode->GetContent(); 1366 wsText.TrimRight(L" "); 1367 FX_BOOL bRet = AppendChar(wsText, fLinePos, fSpaceAbove, bSavePieces); 1368 if (bRet && m_pLoader != NULL) { 1369 m_pLoader->m_pNode = pNode; 1370 } else { 1371 EndBreak(FX_RTFBREAK_ParagraphBreak, fLinePos, bSavePieces); 1372 } 1373 } 1374 FX_BOOL CXFA_TextLayout::LoadRichText(IFDE_XMLNode* pXMLNode, 1375 const CFX_SizeF& szText, 1376 FX_FLOAT& fLinePos, 1377 IFDE_CSSComputedStyle* pParentStyle, 1378 FX_BOOL bSavePieces, 1379 CXFA_LinkUserData* pLinkData, 1380 FX_BOOL bEndBreak, 1381 FX_BOOL bIsOl, 1382 int32_t iLiCount) { 1383 if (pXMLNode == NULL) { 1384 return FALSE; 1385 } 1386 CXFA_TextParseContext* pContext = 1387 m_textParser.GetParseContextFromMap(pXMLNode); 1388 FDE_CSSDISPLAY eDisplay = FDE_CSSDISPLAY_None; 1389 FX_BOOL bContentNode = FALSE; 1390 FX_FLOAT fSpaceBelow = 0; 1391 IFDE_CSSComputedStyle* pStyle = NULL; 1392 CFX_WideString wsName; 1393 if (bEndBreak) { 1394 FX_BOOL bCurOl = FALSE; 1395 FX_BOOL bCurLi = FALSE; 1396 IFDE_XMLElement* pElement = NULL; 1397 if (pContext != NULL) { 1398 if (m_bBlockContinue || 1399 (m_pLoader && pXMLNode == m_pLoader->m_pXMLNode)) { 1400 m_bBlockContinue = TRUE; 1401 } 1402 if (pXMLNode->GetType() == FDE_XMLNODE_Text) { 1403 bContentNode = TRUE; 1404 } else if (pXMLNode->GetType() == FDE_XMLNODE_Element) { 1405 pElement = (IFDE_XMLElement*)pXMLNode; 1406 pElement->GetLocalTagName(wsName); 1407 } 1408 if (wsName == FX_WSTRC(L"ol")) { 1409 bIsOl = TRUE; 1410 bCurOl = TRUE; 1411 } 1412 if (m_bBlockContinue || bContentNode == FALSE) { 1413 eDisplay = pContext->GetDisplay(); 1414 if (eDisplay != FDE_CSSDISPLAY_Block && 1415 eDisplay != FDE_CSSDISPLAY_Inline && 1416 eDisplay != FDE_CSSDISPLAY_ListItem) { 1417 return TRUE; 1418 } 1419 pStyle = m_textParser.ComputeStyle(pXMLNode, pParentStyle); 1420 InitBreak(bContentNode ? pParentStyle : pStyle, eDisplay, szText.x, 1421 pXMLNode, pParentStyle); 1422 if ((eDisplay == FDE_CSSDISPLAY_Block || 1423 eDisplay == FDE_CSSDISPLAY_ListItem) && 1424 (pStyle != NULL) && 1425 (wsName.IsEmpty() || 1426 (wsName != FX_WSTRC(L"body") && wsName != FX_WSTRC(L"html") && 1427 wsName != FX_WSTRC(L"ol") && wsName != FX_WSTRC(L"ul")))) { 1428 const FDE_CSSRECT* pRect = 1429 pStyle->GetBoundaryStyles()->GetMarginWidth(); 1430 if (pRect) { 1431 fLinePos += pRect->top.GetValue(); 1432 fSpaceBelow = pRect->bottom.GetValue(); 1433 } 1434 } 1435 if (wsName == FX_WSTRC(L"a")) { 1436 CFX_WideString wsLinkContent; 1437 FXSYS_assert(pElement); 1438 pElement->GetString(FX_WSTRC(L"href").GetPtr(), wsLinkContent); 1439 if (!wsLinkContent.IsEmpty()) { 1440 pLinkData = FDE_NewWith(m_pAllocator) CXFA_LinkUserData( 1441 m_pAllocator, 1442 wsLinkContent.GetBuffer(wsLinkContent.GetLength())); 1443 wsLinkContent.ReleaseBuffer(wsLinkContent.GetLength()); 1444 } 1445 } 1446 int32_t iTabCount = 1447 m_textParser.CountTabs(bContentNode ? pParentStyle : pStyle); 1448 FX_BOOL bSpaceRun = 1449 m_textParser.IsSpaceRun(bContentNode ? pParentStyle : pStyle); 1450 CFX_WideString wsText; 1451 if (bContentNode && iTabCount == 0) { 1452 ((IFDE_XMLText*)pXMLNode)->GetText(wsText); 1453 } else if (wsName == FX_WSTRC(L"br")) { 1454 wsText = L'\n'; 1455 } else if (wsName == FX_WSTRC(L"li")) { 1456 bCurLi = TRUE; 1457 if (bIsOl) { 1458 wsText.Format(L"%d. ", iLiCount); 1459 } else { 1460 wsText = 0x00B7 + FX_WSTRC(L" "); 1461 } 1462 } else if (!bContentNode) { 1463 if (iTabCount > 0) 1464 while (iTabCount-- > 0) { 1465 wsText += L'\t'; 1466 } 1467 else { 1468 m_textParser.GetEmbbedObj(m_pTextProvider, pXMLNode, wsText); 1469 } 1470 } 1471 int32_t iLength = wsText.GetLength(); 1472 if (iLength > 0 && bContentNode && !bSpaceRun) { 1473 ProcessText(wsText); 1474 } 1475 if (m_pLoader) { 1476 if (wsText.GetLength() > 0 && 1477 (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) { 1478 wsText.TrimLeft(0x20); 1479 } 1480 if (FDE_CSSDISPLAY_Block == eDisplay) { 1481 m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; 1482 } else if (FDE_CSSDISPLAY_Inline == eDisplay && 1483 (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) { 1484 m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; 1485 } else if (wsText.GetLength() > 0 && 1486 (0x20 == wsText.GetAt(wsText.GetLength() - 1))) { 1487 m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; 1488 } else if (wsText.GetLength() == 0) 1489 ; 1490 else { 1491 m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; 1492 } 1493 } 1494 if (wsText.GetLength() > 0) { 1495 if (m_pLoader == NULL || m_pLoader->m_iChar == 0) { 1496 if (pLinkData) { 1497 pLinkData->AddRef(); 1498 } 1499 CXFA_TextUserData* pUserData = FDE_NewWith(m_pAllocator) 1500 CXFA_TextUserData(m_pAllocator, 1501 bContentNode ? pParentStyle : pStyle, 1502 pLinkData); 1503 m_pBreak->SetUserData(pUserData); 1504 } 1505 if (AppendChar(wsText, fLinePos, 0, bSavePieces)) { 1506 if (m_pLoader) { 1507 m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE; 1508 } 1509 if (IsEnd(bSavePieces)) { 1510 if (m_pLoader && m_pLoader->m_iTotalLines > -1) { 1511 m_pLoader->m_pXMLNode = pXMLNode; 1512 m_pLoader->m_pParentStyle = pParentStyle; 1513 } 1514 if (pStyle != NULL) { 1515 pStyle->Release(); 1516 } 1517 return FALSE; 1518 } 1519 return TRUE; 1520 } 1521 } 1522 } 1523 } 1524 FX_BOOL ret = TRUE; 1525 for (IFDE_XMLNode* pChildNode = 1526 pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild); 1527 pChildNode; 1528 pChildNode = pChildNode->GetNodeItem(IFDE_XMLNode::NextSibling)) { 1529 if (bCurOl) { 1530 iLiCount++; 1531 } 1532 ret = LoadRichText(pChildNode, szText, fLinePos, 1533 pContext ? pStyle : pParentStyle, bSavePieces, 1534 pLinkData, TRUE, bIsOl, iLiCount); 1535 if (ret == FALSE) { 1536 return FALSE; 1537 } 1538 } 1539 if (m_pLoader) { 1540 if (FDE_CSSDISPLAY_Block == eDisplay) { 1541 m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE; 1542 } 1543 } 1544 if (bCurLi) { 1545 EndBreak(FX_RTFBREAK_LineBreak, fLinePos, bSavePieces); 1546 } 1547 } else { 1548 if (pContext != NULL) { 1549 eDisplay = pContext->GetDisplay(); 1550 } 1551 } 1552 if (m_bBlockContinue) { 1553 if (pContext != NULL && !bContentNode) { 1554 FX_DWORD dwStatus = (eDisplay == FDE_CSSDISPLAY_Block) 1555 ? FX_RTFBREAK_ParagraphBreak 1556 : FX_RTFBREAK_PieceBreak; 1557 EndBreak(dwStatus, fLinePos, bSavePieces); 1558 if (eDisplay == FDE_CSSDISPLAY_Block) { 1559 fLinePos += fSpaceBelow; 1560 if (m_pTabstopContext) { 1561 m_pTabstopContext->RemoveAll(); 1562 } 1563 } 1564 if (wsName == FX_WSTRC(L"a")) { 1565 if (pLinkData) { 1566 pLinkData->Release(); 1567 pLinkData = nullptr; 1568 } 1569 } 1570 if (IsEnd(bSavePieces)) { 1571 if (pStyle) { 1572 pStyle->Release(); 1573 } 1574 if (m_pLoader && m_pLoader->m_iTotalLines > -1) { 1575 m_pLoader->m_pXMLNode = 1576 pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling); 1577 m_pLoader->m_pParentStyle = pParentStyle; 1578 } 1579 return FALSE; 1580 } 1581 } 1582 } 1583 if (pStyle != NULL) { 1584 pStyle->Release(); 1585 } 1586 return TRUE; 1587 } 1588 FX_BOOL CXFA_TextLayout::AppendChar(const CFX_WideString& wsText, 1589 FX_FLOAT& fLinePos, 1590 FX_FLOAT fSpaceAbove, 1591 FX_BOOL bSavePieces) { 1592 FX_DWORD dwStatus = 0; 1593 int32_t iChar = 0; 1594 if (m_pLoader) { 1595 iChar = m_pLoader->m_iChar; 1596 } 1597 int32_t iLength = wsText.GetLength(); 1598 for (int32_t i = iChar; i < iLength; i++) { 1599 FX_WCHAR wch = wsText.GetAt(i); 1600 if (wch == 0xA0) { 1601 wch = 0x20; 1602 } 1603 if ((dwStatus = m_pBreak->AppendChar(wch)) > FX_RTFBREAK_PieceBreak) { 1604 AppendTextLine(dwStatus, fLinePos, bSavePieces); 1605 if (IsEnd(bSavePieces)) { 1606 if (m_pLoader != NULL) { 1607 m_pLoader->m_iChar = i; 1608 } 1609 return TRUE; 1610 } 1611 if (dwStatus == FX_RTFBREAK_ParagraphBreak && m_bRichText) { 1612 fLinePos += fSpaceAbove; 1613 } 1614 } 1615 } 1616 if (m_pLoader) { 1617 m_pLoader->m_iChar = 0; 1618 } 1619 return FALSE; 1620 } 1621 FX_BOOL CXFA_TextLayout::IsEnd(FX_BOOL bSavePieces) { 1622 if (!bSavePieces) { 1623 return FALSE; 1624 } 1625 if (m_pLoader && m_pLoader->m_iTotalLines > 0) { 1626 return m_iLines >= m_pLoader->m_iTotalLines; 1627 } 1628 return FALSE; 1629 } 1630 void CXFA_TextLayout::ProcessText(CFX_WideString& wsText) { 1631 int32_t iLen = wsText.GetLength(); 1632 if (iLen == 0) { 1633 return; 1634 } 1635 FX_WCHAR* psz = wsText.GetBuffer(iLen); 1636 int32_t iTrimLeft = 0; 1637 FX_WCHAR wch = 0, wPrev = 0; 1638 for (int32_t i = 0; i < iLen; i++) { 1639 wch = psz[i]; 1640 if (wch < 0x20) { 1641 wch = 0x20; 1642 } 1643 if (wch == 0x20 && wPrev == 0x20) { 1644 continue; 1645 } 1646 wPrev = wch; 1647 psz[iTrimLeft++] = wch; 1648 } 1649 wsText.ReleaseBuffer(iLen); 1650 wsText = wsText.Left(iTrimLeft); 1651 } 1652 void CXFA_TextLayout::EndBreak(FX_DWORD dwStatus, 1653 FX_FLOAT& fLinePos, 1654 FX_BOOL bSavePieces) { 1655 dwStatus = m_pBreak->EndBreak(dwStatus); 1656 if (dwStatus > FX_RTFBREAK_PieceBreak) { 1657 AppendTextLine(dwStatus, fLinePos, bSavePieces, TRUE); 1658 } 1659 } 1660 void CXFA_TextLayout::DoTabstops(IFDE_CSSComputedStyle* pStyle, 1661 CXFA_PieceLine* pPieceLine) { 1662 if (m_pTabstopContext == NULL || m_pTabstopContext->m_iTabCount == 0) { 1663 return; 1664 } 1665 if (pStyle == NULL || pPieceLine == NULL) { 1666 return; 1667 } 1668 int32_t iPieces = pPieceLine->m_textPieces.GetSize(); 1669 if (iPieces == 0) { 1670 return; 1671 } 1672 XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPieces - 1); 1673 int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex; 1674 int32_t iCount = m_textParser.CountTabs(pStyle); 1675 if (iTabstopsIndex > m_pTabstopContext->m_iTabCount - 1) { 1676 return; 1677 } 1678 if (iCount > 0) { 1679 iTabstopsIndex++; 1680 m_pTabstopContext->m_bTabstops = TRUE; 1681 FX_FLOAT fRight = 0; 1682 if (iPieces > 1) { 1683 XFA_LPTEXTPIECE p = pPieceLine->m_textPieces.GetAt(iPieces - 2); 1684 fRight = p->rtPiece.right(); 1685 } 1686 m_pTabstopContext->m_fTabWidth = 1687 pPiece->rtPiece.width + pPiece->rtPiece.left - fRight; 1688 } else if (iTabstopsIndex > -1) { 1689 FX_FLOAT fLeft = 0; 1690 if (m_pTabstopContext->m_bTabstops) { 1691 XFA_TABSTOPS* pTabstops = 1692 m_pTabstopContext->m_tabstops.GetDataPtr(iTabstopsIndex); 1693 FX_DWORD dwAlgin = pTabstops->dwAlign; 1694 if (dwAlgin == FX_HashCode_String_GetW(L"center", 6)) { 1695 fLeft = pPiece->rtPiece.width / 2.0f; 1696 } else if (dwAlgin == FX_HashCode_String_GetW(L"right", 5) || 1697 dwAlgin == FX_HashCode_String_GetW(L"before", 6)) { 1698 fLeft = pPiece->rtPiece.width; 1699 } else if (dwAlgin == FX_HashCode_String_GetW(L"decimal", 7)) { 1700 int32_t iChars = pPiece->iChars; 1701 for (int32_t i = 0; i < iChars; i++) { 1702 if (pPiece->pszText[i] == L'.') { 1703 break; 1704 } 1705 fLeft += pPiece->pWidths[i] / 20000.0f; 1706 } 1707 } 1708 m_pTabstopContext->m_fLeft = 1709 std::min(fLeft, m_pTabstopContext->m_fTabWidth); 1710 m_pTabstopContext->m_bTabstops = FALSE; 1711 m_pTabstopContext->m_fTabWidth = 0; 1712 } 1713 pPiece->rtPiece.left -= m_pTabstopContext->m_fLeft; 1714 } 1715 } 1716 void CXFA_TextLayout::AppendTextLine(FX_DWORD dwStatus, 1717 FX_FLOAT& fLinePos, 1718 FX_BOOL bSavePieces, 1719 FX_BOOL bEndBreak) { 1720 int32_t iPieces = m_pBreak->CountBreakPieces(); 1721 if (iPieces < 1) { 1722 return; 1723 } 1724 IFDE_CSSComputedStyle* pStyle = NULL; 1725 if (bSavePieces) { 1726 CXFA_PieceLine* pPieceLine = FDE_NewWith(m_pAllocator) CXFA_PieceLine; 1727 m_pieceLines.Add(pPieceLine); 1728 if (m_pTabstopContext) { 1729 m_pTabstopContext->Reset(); 1730 } 1731 FX_FLOAT fLineStep = 0, fBaseLine = 0; 1732 int32_t i = 0; 1733 for (i = 0; i < iPieces; i++) { 1734 const CFX_RTFPiece* pPiece = m_pBreak->GetBreakPiece(i); 1735 CXFA_TextUserData* pUserData = (CXFA_TextUserData*)pPiece->m_pUserData; 1736 if (pUserData != NULL) { 1737 pStyle = pUserData->m_pStyle; 1738 } 1739 FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f; 1740 XFA_LPTEXTPIECE pTP = 1741 (XFA_LPTEXTPIECE)m_pAllocator->Alloc(sizeof(XFA_TEXTPIECE)); 1742 pTP->pszText = 1743 (FX_WCHAR*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(FX_WCHAR)); 1744 pTP->pWidths = 1745 (int32_t*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(int32_t)); 1746 pTP->iChars = pPiece->m_iChars; 1747 pPiece->GetString(pTP->pszText); 1748 pPiece->GetWidths(pTP->pWidths); 1749 pTP->iBidiLevel = pPiece->m_iBidiLevel; 1750 pTP->iHorScale = pPiece->m_iHorizontalScale; 1751 pTP->iVerScale = pPiece->m_iVerticalScale; 1752 m_textParser.GetUnderline(m_pTextProvider, pStyle, pTP->iUnderline, 1753 pTP->iPeriod); 1754 m_textParser.GetLinethrough(m_pTextProvider, pStyle, pTP->iLineThrough); 1755 pTP->dwColor = m_textParser.GetColor(m_pTextProvider, pStyle); 1756 pTP->pFont = m_textParser.GetFont(m_pTextProvider, pStyle); 1757 pTP->fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle); 1758 pTP->rtPiece.left = pPiece->m_iStartPos / 20000.0f; 1759 pTP->rtPiece.width = pPiece->m_iWidth / 20000.0f; 1760 pTP->rtPiece.height = (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f; 1761 FX_FLOAT fBaseLineTemp = 1762 m_textParser.GetBaseline(m_pTextProvider, pStyle); 1763 pTP->rtPiece.top = fBaseLineTemp; 1764 pPieceLine->m_textPieces.Add(pTP); 1765 FX_FLOAT fLineHeight = m_textParser.GetLineHeight( 1766 m_pTextProvider, pStyle, m_iLines == 0, fVerScale); 1767 if (fBaseLineTemp > 0) { 1768 FX_FLOAT fLineHeightTmp = fBaseLineTemp + pTP->rtPiece.height; 1769 if (fLineHeight < fLineHeightTmp) { 1770 fLineHeight = fLineHeightTmp; 1771 } else { 1772 fBaseLineTemp = 0; 1773 } 1774 } else if (fBaseLine < -fBaseLineTemp) { 1775 fBaseLine = -fBaseLineTemp; 1776 } 1777 fLineStep = std::max(fLineStep, fLineHeight); 1778 if (pUserData != NULL && pUserData->m_pLinkData != NULL) { 1779 pUserData->m_pLinkData->AddRef(); 1780 pTP->pLinkData = pUserData->m_pLinkData; 1781 } else { 1782 pTP->pLinkData = NULL; 1783 } 1784 DoTabstops(pStyle, pPieceLine); 1785 } 1786 for (i = 0; i < iPieces; i++) { 1787 XFA_LPTEXTPIECE pTP = pPieceLine->m_textPieces.GetAt(i); 1788 FX_FLOAT& fTop = pTP->rtPiece.top; 1789 FX_FLOAT fBaseLineTemp = fTop; 1790 fTop = fLinePos + fLineStep - pTP->rtPiece.height - fBaseLineTemp; 1791 fTop = std::max(0.0f, fTop); 1792 } 1793 fLinePos += fLineStep + fBaseLine; 1794 } else { 1795 FX_FLOAT fLineStep = 0; 1796 FX_FLOAT fLineWidth = 0; 1797 for (int32_t i = 0; i < iPieces; i++) { 1798 const CFX_RTFPiece* pPiece = m_pBreak->GetBreakPiece(i); 1799 CXFA_TextUserData* pUserData = (CXFA_TextUserData*)pPiece->m_pUserData; 1800 if (pUserData != NULL) { 1801 pStyle = pUserData->m_pStyle; 1802 } 1803 FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f; 1804 FX_FLOAT fBaseLine = m_textParser.GetBaseline(m_pTextProvider, pStyle); 1805 FX_FLOAT fLineHeight = m_textParser.GetLineHeight( 1806 m_pTextProvider, pStyle, m_iLines == 0, fVerScale); 1807 if (fBaseLine > 0) { 1808 FX_FLOAT fLineHeightTmp = 1809 fBaseLine + (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f; 1810 if (fLineHeight < fLineHeightTmp) { 1811 fLineHeight = fLineHeightTmp; 1812 } 1813 } 1814 fLineStep = std::max(fLineStep, fLineHeight); 1815 fLineWidth += pPiece->m_iWidth / 20000.0f; 1816 } 1817 fLinePos += fLineStep; 1818 m_fMaxWidth = std::max(m_fMaxWidth, fLineWidth); 1819 if (m_pLoader && m_pLoader->m_bSaveLineHeight) { 1820 FX_FLOAT fHeight = fLinePos - m_pLoader->m_fLastPos; 1821 m_pLoader->m_fLastPos = fLinePos; 1822 m_pLoader->m_lineHeights.Add(fHeight); 1823 } 1824 } 1825 if (pStyle) { 1826 pStyle->AddRef(); 1827 } 1828 m_pBreak->ClearBreakPieces(); 1829 if (dwStatus == FX_RTFBREAK_ParagraphBreak) { 1830 m_pBreak->Reset(); 1831 if (!pStyle && bEndBreak) { 1832 CXFA_Para para = m_pTextProvider->GetParaNode(); 1833 if (para.IsExistInXML()) { 1834 FX_FLOAT fStartPos = para.GetMarginLeft(); 1835 FX_FLOAT fIndent = para.GetTextIndent(); 1836 if (fIndent > 0) { 1837 fStartPos += fIndent; 1838 } 1839 FX_FLOAT fSpaceBelow = para.GetSpaceBelow(); 1840 if (fSpaceBelow < 0.1f) { 1841 fSpaceBelow = 0; 1842 } 1843 m_pBreak->SetLineStartPos(fStartPos); 1844 fLinePos += fSpaceBelow; 1845 } 1846 } 1847 } 1848 if (pStyle) { 1849 FX_FLOAT fStart = 0; 1850 const FDE_CSSRECT* pRect = pStyle->GetBoundaryStyles()->GetMarginWidth(); 1851 if (pRect) { 1852 fStart = pRect->left.GetValue(); 1853 } 1854 FX_FLOAT fTextIndent = 1855 pStyle->GetParagraphStyles()->GetTextIndent().GetValue(); 1856 if (fTextIndent < 0) { 1857 fStart -= fTextIndent; 1858 } 1859 m_pBreak->SetLineStartPos(fStart); 1860 pStyle->Release(); 1861 } 1862 m_iLines++; 1863 } 1864 void CXFA_TextLayout::RenderString(IFDE_RenderDevice* pDevice, 1865 IFDE_SolidBrush* pBrush, 1866 CXFA_PieceLine* pPieceLine, 1867 int32_t iPiece, 1868 FXTEXT_CHARPOS* pCharPos, 1869 const CFX_Matrix& tmDoc2Device) { 1870 XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPiece); 1871 int32_t iCount = GetDisplayPos(pPiece, pCharPos); 1872 if (iCount > 0) { 1873 pBrush->SetColor(pPiece->dwColor); 1874 pDevice->DrawString(pBrush, pPiece->pFont, pCharPos, iCount, 1875 pPiece->fFontSize, &tmDoc2Device); 1876 } 1877 pPieceLine->m_charCounts.Add(iCount); 1878 } 1879 void CXFA_TextLayout::RenderPath(IFDE_RenderDevice* pDevice, 1880 IFDE_Pen* pPen, 1881 CXFA_PieceLine* pPieceLine, 1882 int32_t iPiece, 1883 FXTEXT_CHARPOS* pCharPos, 1884 const CFX_Matrix& tmDoc2Device) { 1885 XFA_TEXTPIECE* pPiece = pPieceLine->m_textPieces.GetAt(iPiece); 1886 FX_BOOL bNoUnderline = pPiece->iUnderline < 1 || pPiece->iUnderline > 2; 1887 FX_BOOL bNoLineThrough = pPiece->iLineThrough < 1 || pPiece->iLineThrough > 2; 1888 if (bNoUnderline && bNoLineThrough) { 1889 return; 1890 } 1891 pPen->SetColor(pPiece->dwColor); 1892 IFDE_Path* pPath = IFDE_Path::Create(); 1893 int32_t iChars = GetDisplayPos(pPiece, pCharPos); 1894 if (iChars > 0) { 1895 CFX_PointF pt1, pt2; 1896 FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f; 1897 int32_t i = 0; 1898 if (pPiece->iPeriod == XFA_ATTRIBUTEENUM_Word) { 1899 for (int32_t i = 0; i < pPiece->iUnderline; i++) { 1900 for (int32_t j = 0; j < iChars; j++) { 1901 pt1.x = pCharPos[j].m_OriginX; 1902 pt2.x = 1903 pt1.x + pCharPos[j].m_FontCharWidth * pPiece->fFontSize / 1000.0f; 1904 pt1.y = pt2.y = fEndY; 1905 pPath->AddLine(pt1, pt2); 1906 } 1907 fEndY += 2.0f; 1908 } 1909 } else { 1910 pt1.x = pCharPos[0].m_OriginX; 1911 pt2.x = 1912 pCharPos[iChars - 1].m_OriginX + 1913 pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; 1914 for (int32_t i = 0; i < pPiece->iUnderline; i++) { 1915 pt1.y = pt2.y = fEndY; 1916 pPath->AddLine(pt1, pt2); 1917 fEndY += 2.0f; 1918 } 1919 } 1920 fEndY = pCharPos[0].m_OriginY - pPiece->rtPiece.height * 0.25f; 1921 pt1.x = pCharPos[0].m_OriginX; 1922 pt2.x = pCharPos[iChars - 1].m_OriginX + 1923 pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; 1924 for (i = 0; i < pPiece->iLineThrough; i++) { 1925 pt1.y = pt2.y = fEndY; 1926 pPath->AddLine(pt1, pt2); 1927 fEndY += 2.0f; 1928 } 1929 } else { 1930 if (bNoLineThrough && 1931 (bNoUnderline || pPiece->iPeriod != XFA_ATTRIBUTEENUM_All)) { 1932 goto XFA_RenderPathRet; 1933 } 1934 int32_t iCharsTmp = 0; 1935 int32_t iPiecePrev = iPiece, iPieceNext = iPiece; 1936 while (iPiecePrev > 0) { 1937 iPiecePrev--; 1938 iCharsTmp = pPieceLine->m_charCounts.GetAt(iPiecePrev); 1939 if (iCharsTmp > 0) { 1940 break; 1941 } 1942 } 1943 if (iCharsTmp == 0) { 1944 goto XFA_RenderPathRet; 1945 } 1946 iCharsTmp = 0; 1947 int32_t iPieces = pPieceLine->m_textPieces.GetSize(); 1948 while (iPieceNext < iPieces - 1) { 1949 iPieceNext++; 1950 iCharsTmp = pPieceLine->m_charCounts.GetAt(iPieceNext); 1951 if (iCharsTmp > 0) { 1952 break; 1953 } 1954 } 1955 if (iCharsTmp == 0) { 1956 goto XFA_RenderPathRet; 1957 } 1958 FX_FLOAT fOrgX = 0.0f, fEndX = 0.0f; 1959 pPiece = pPieceLine->m_textPieces.GetAt(iPiecePrev); 1960 iChars = GetDisplayPos(pPiece, pCharPos); 1961 if (iChars < 1) { 1962 goto XFA_RenderPathRet; 1963 } 1964 fOrgX = pCharPos[iChars - 1].m_OriginX + 1965 pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f; 1966 pPiece = pPieceLine->m_textPieces.GetAt(iPieceNext); 1967 iChars = GetDisplayPos(pPiece, pCharPos); 1968 if (iChars < 1) { 1969 goto XFA_RenderPathRet; 1970 } 1971 fEndX = pCharPos[0].m_OriginX; 1972 CFX_PointF pt1, pt2; 1973 pt1.x = fOrgX, pt2.x = fEndX; 1974 FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f; 1975 int32_t i = 0; 1976 for (i = 0; i < pPiece->iUnderline; i++) { 1977 pt1.y = pt2.y = fEndY; 1978 pPath->AddLine(pt1, pt2); 1979 fEndY += 2.0f; 1980 } 1981 fEndY = pCharPos[0].m_OriginY - pPiece->rtPiece.height * 0.25f; 1982 for (i = 0; i < pPiece->iLineThrough; i++) { 1983 pt1.y = pt2.y = fEndY; 1984 pPath->AddLine(pt1, pt2); 1985 fEndY += 2.0f; 1986 } 1987 } 1988 pDevice->DrawPath(pPen, 1, pPath, &tmDoc2Device); 1989 XFA_RenderPathRet: 1990 pPath->Release(); 1991 } 1992 int32_t CXFA_TextLayout::GetDisplayPos(XFA_LPCTEXTPIECE pPiece, 1993 FXTEXT_CHARPOS* pCharPos, 1994 FX_BOOL bCharCode) { 1995 if (pPiece == NULL) { 1996 return 0; 1997 } 1998 FX_RTFTEXTOBJ tr; 1999 if (!ToRun(pPiece, tr)) { 2000 return 0; 2001 } 2002 return m_pBreak->GetDisplayPos(&tr, pCharPos, bCharCode); 2003 } 2004 FX_BOOL CXFA_TextLayout::ToRun(XFA_LPCTEXTPIECE pPiece, FX_RTFTEXTOBJ& tr) { 2005 int32_t iLength = pPiece->iChars; 2006 if (iLength < 1) { 2007 return FALSE; 2008 } 2009 tr.pStr = pPiece->pszText; 2010 tr.pFont = pPiece->pFont; 2011 tr.pRect = &pPiece->rtPiece; 2012 tr.pWidths = pPiece->pWidths; 2013 tr.iLength = iLength; 2014 tr.fFontSize = pPiece->fFontSize; 2015 tr.iBidiLevel = pPiece->iBidiLevel; 2016 tr.iCharRotation = 0; 2017 tr.wLineBreakChar = L'\n'; 2018 tr.iVerticalScale = pPiece->iVerScale; 2019 tr.dwLayoutStyles = FX_RTFLAYOUTSTYLE_ExpandTab; 2020 tr.iHorizontalScale = pPiece->iHorScale; 2021 return TRUE; 2022 } 2023