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