Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: xfa/src/fxfa/app/xfa_textlayout.cpp

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

Powered by Google App Engine
This is Rietveld 408576698