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"
~CXFA_CSSTagProvider()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 }
GetNextAttribute(FX_POSITION & pos,CFX_WideStringC & wsAttr,CFX_WideStringC & wsValue)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 }
SetAttribute(const CFX_WideString & wsAttr,const CFX_WideString & wsValue)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 }
SetDecls(const IFDE_CSSDeclaration ** ppDeclArray,int32_t iDeclCount)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 }
~CXFA_TextParser()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 }
Reset()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 }
InitCSSData(IXFA_TextProvider * pTextProvider)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 }
LoadDefaultSheetStyle()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 }
CreateRootStyle(IXFA_TextProvider * pTextProvider)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 }
CreateStyle(IFDE_CSSComputedStyle * pParentStyle)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 }
ComputeStyle(IFDE_XMLNode * pXMLNode,IFDE_CSSComputedStyle * pParentStyle)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 }
DoParse(IFDE_XMLNode * pXMLContainer,IXFA_TextProvider * pTextProvider)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 }
ParseRichText(IFDE_XMLNode * pXMLNode,IFDE_CSSComputedStyle * pParentStyle)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 }
ParseTagInfo(IFDE_XMLNode * pXMLNode,CXFA_CSSTagProvider & tagProvider)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 }
GetVAlgin(IXFA_TextProvider * pTextProvider) const324 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 }
GetTabInterval(IFDE_CSSComputedStyle * pStyle) const332 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 }
CountTabs(IFDE_CSSComputedStyle * pStyle) const340 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 }
IsSpaceRun(IFDE_CSSComputedStyle * pStyle) const347 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 }
GetFont(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle) const355 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 }
GetFontSize(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle) const388 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 }
GetHorScale(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle,IFDE_XMLNode * pXMLNode) const399 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 }
GetVerScale(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle) const424 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 }
GetUnderline(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle,int32_t & iUnderline,int32_t & iPeriod) const437 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 }
GetLinethrough(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle,int32_t & iLinethrough) const466 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 }
GetColor(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle) const479 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 }
GetBaseline(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle) const489 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 }
GetLineHeight(IXFA_TextProvider * pTextProvider,IFDE_CSSComputedStyle * pStyle,FX_BOOL bFirst,FX_FLOAT fVerScale) const501 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 }
GetEmbbedObj(IXFA_TextProvider * pTextProvider,IFDE_XMLNode * pXMLNode,CFX_WideString & wsValue)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 }
GetParseContextFromMap(IFDE_XMLNode * pXMLNode)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 };
GetTabstops(IFDE_CSSComputedStyle * pStyle,CXFA_TextTabstopsContext * pTabstopContext)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 }
CXFA_TextLayout(IXFA_TextProvider * pTextProvider)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 }
~CXFA_TextLayout()687 CXFA_TextLayout::~CXFA_TextLayout() {
688   m_textParser.Reset();
689   delete m_pLoader;
690   delete m_pTabstopContext;
691   Unload();
692 }
Unload()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 }
GetPieceLines()709 const CXFA_PieceLineArray* CXFA_TextLayout::GetPieceLines() {
710   return &m_pieceLines;
711 }
GetTextDataNode()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 }
GetXMLContainerNode()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 }
CreateBreak(FX_BOOL bDefault)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 }
InitBreak(FX_FLOAT fLineWidth)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 }
InitBreak(IFDE_CSSComputedStyle * pStyle,FDE_CSSDISPLAY eDisplay,FX_FLOAT fLineWidth,IFDE_XMLNode * pXMLNode,IFDE_CSSComputedStyle * pParentStyle)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 }
GetText(CFX_WideString & wsText)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 }
GetLayoutHeight()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 }
StartLayout(FX_FLOAT fWidth)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 }
DoLayout(int32_t iBlockIndex,FX_FLOAT & fCalcHeight,FX_FLOAT fContentAreaHeight,FX_FLOAT fTextHeight)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 }
CountBlocks() const1033 int32_t CXFA_TextLayout::CountBlocks() const {
1034   int32_t iCount = m_Blocks.GetSize() / 2;
1035   return iCount > 0 ? iCount : 1;
1036 }
CalcSize(const CFX_SizeF & minSize,const CFX_SizeF & maxSize,CFX_SizeF & defaultSize)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 }
Layout(const CFX_SizeF & size,FX_FLOAT * fHeight)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 }
Layout(int32_t iBlock)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 }
ItemBlocks(const CFX_RectF & rtText,int32_t iBlockIndex)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 }
DrawString(CFX_RenderDevice * pFxDevice,const CFX_Matrix & tmDoc2Device,const CFX_RectF & rtClip,int32_t iBlock)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 }
UpdateAlign(FX_FLOAT fHeight,FX_FLOAT fBottom)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 }
Loader(const CFX_SizeF & szText,FX_FLOAT & fLinePos,FX_BOOL bSavePieces)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 }
LoadText(CXFA_Node * pNode,const CFX_SizeF & szText,FX_FLOAT & fLinePos,FX_BOOL bSavePieces)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 }
LoadRichText(IFDE_XMLNode * pXMLNode,const CFX_SizeF & szText,FX_FLOAT & fLinePos,IFDE_CSSComputedStyle * pParentStyle,FX_BOOL bSavePieces,CXFA_LinkUserData * pLinkData,FX_BOOL bEndBreak,FX_BOOL bIsOl,int32_t iLiCount)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 }
AppendChar(const CFX_WideString & wsText,FX_FLOAT & fLinePos,FX_FLOAT fSpaceAbove,FX_BOOL bSavePieces)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 }
IsEnd(FX_BOOL bSavePieces)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 }
ProcessText(CFX_WideString & wsText)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 }
EndBreak(FX_DWORD dwStatus,FX_FLOAT & fLinePos,FX_BOOL bSavePieces)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 }
DoTabstops(IFDE_CSSComputedStyle * pStyle,CXFA_PieceLine * pPieceLine)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 }
AppendTextLine(FX_DWORD dwStatus,FX_FLOAT & fLinePos,FX_BOOL bSavePieces,FX_BOOL bEndBreak)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 }
RenderString(IFDE_RenderDevice * pDevice,IFDE_SolidBrush * pBrush,CXFA_PieceLine * pPieceLine,int32_t iPiece,FXTEXT_CHARPOS * pCharPos,const CFX_Matrix & tmDoc2Device)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 }
RenderPath(IFDE_RenderDevice * pDevice,IFDE_Pen * pPen,CXFA_PieceLine * pPieceLine,int32_t iPiece,FXTEXT_CHARPOS * pCharPos,const CFX_Matrix & tmDoc2Device)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 }
GetDisplayPos(XFA_LPCTEXTPIECE pPiece,FXTEXT_CHARPOS * pCharPos,FX_BOOL bCharCode)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 }
ToRun(XFA_LPCTEXTPIECE pPiece,FX_RTFTEXTOBJ & tr)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