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