diff options
Diffstat (limited to 'xfa/src/fxfa/src/app/xfa_textlayout.cpp')
-rw-r--r-- | xfa/src/fxfa/src/app/xfa_textlayout.cpp | 1927 |
1 files changed, 1927 insertions, 0 deletions
diff --git a/xfa/src/fxfa/src/app/xfa_textlayout.cpp b/xfa/src/fxfa/src/app/xfa_textlayout.cpp new file mode 100644 index 0000000000..5a4eee48f5 --- /dev/null +++ b/xfa/src/fxfa/src/app/xfa_textlayout.cpp @@ -0,0 +1,1927 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../../foxitlib.h"
+#include "../common/xfa_common.h"
+#include "xfa_textlayout.h"
+#include "xfa_ffapp.h"
+#include "xfa_ffdoc.h"
+#include "xfa_fontmgr.h"
+CXFA_CSSTagProvider::~CXFA_CSSTagProvider()
+{
+ FX_POSITION pos = m_Attributes.GetStartPosition();
+ while (pos) {
+ CFX_WideString* pName = NULL, *pValue = NULL;
+ m_Attributes.GetNextAssoc(pos, (void*&)pName, (void*&)pValue);
+ if (pName != NULL) {
+ delete pName;
+ }
+ if (pValue != NULL) {
+ delete pValue;
+ }
+ }
+}
+void CXFA_CSSTagProvider::GetNextAttribute(FX_POSITION &pos, CFX_WideStringC &wsAttr, CFX_WideStringC &wsValue)
+{
+ if (pos == NULL) {
+ return;
+ }
+ CFX_WideString *pName = NULL;
+ CFX_WideString *pValue = NULL;
+ m_Attributes.GetNextAssoc(pos, (void*&)pName, (void*&)pValue);
+ wsAttr = *pName;
+ wsValue = *pValue;
+}
+void CXFA_CSSTagProvider::SetAttribute(const CFX_WideString &wsAttr, const CFX_WideString &wsValue)
+{
+ CFX_WideString *pName = FX_NEW CFX_WideString();
+ CFX_WideString *pValue = FX_NEW CFX_WideString();
+ *pName = wsAttr;
+ *pValue = wsValue;
+ m_Attributes.SetAt(pName, pValue);
+}
+void CXFA_TextParseContext::SetDecls(const IFDE_CSSDeclaration **ppDeclArray, FX_INT32 iDeclCount)
+{
+ if (iDeclCount <= 0 || ppDeclArray == NULL) {
+ return;
+ }
+ m_dwMatchedDecls = iDeclCount;
+ FX_INT32 iBytes = iDeclCount * sizeof(IFDE_CSSDeclaration*);
+ m_ppMatchedDecls = (IFDE_CSSDeclaration**)FDE_Alloc(iBytes);
+ FX_memcpy(m_ppMatchedDecls, ppDeclArray, iBytes);
+}
+CXFA_TextParser::~CXFA_TextParser()
+{
+ if (m_pUASheet != NULL) {
+ m_pUASheet->Release();
+ }
+ if (m_pSelector != NULL) {
+ m_pSelector->Release();
+ }
+ if (m_pAllocator != NULL) {
+ m_pAllocator->Release();
+ }
+ FX_POSITION ps = m_mapXMLNodeToParseContext.GetStartPosition();
+ while (ps) {
+ IFDE_XMLNode *pXMLNode;
+ CXFA_TextParseContext *pParseContext;
+ m_mapXMLNodeToParseContext.GetNextAssoc(ps, pXMLNode, pParseContext);
+ if (pParseContext != NULL) {
+ FDE_DeleteWith(CXFA_TextParseContext, m_pAllocator, pParseContext);
+ }
+ }
+ m_mapXMLNodeToParseContext.RemoveAll();
+}
+void CXFA_TextParser::Reset()
+{
+ FX_POSITION ps = m_mapXMLNodeToParseContext.GetStartPosition();
+ while (ps) {
+ IFDE_XMLNode *pXMLNode;
+ CXFA_TextParseContext *pParseContext;
+ m_mapXMLNodeToParseContext.GetNextAssoc(ps, pXMLNode, pParseContext);
+ if (pParseContext != NULL) {
+ FDE_DeleteWith(CXFA_TextParseContext, m_pAllocator, pParseContext);
+ }
+ }
+ m_mapXMLNodeToParseContext.RemoveAll();
+ if (m_pAllocator != NULL) {
+ m_pAllocator->Release();
+ m_pAllocator = NULL;
+ }
+}
+void CXFA_TextParser::InitCSSData(IXFA_TextProvider *pTextProvider)
+{
+ if (pTextProvider == NULL) {
+ return;
+ }
+ if (m_pSelector == NULL) {
+ CXFA_FFDoc *pDoc = pTextProvider->GetDocNode();
+ IFX_FontMgr *pFontMgr = pDoc->GetApp()->GetFDEFontMgr();
+ FXSYS_assert(pFontMgr != NULL);
+ m_pSelector = IFDE_CSSStyleSelector::Create();
+ m_pSelector->SetFontMgr(pFontMgr);
+ FX_FLOAT fFontSize = 10;
+ CXFA_Font font = pTextProvider->GetFontNode();
+ if (font.IsExistInXML()) {
+ fFontSize = font.GetFontSize();
+ }
+ m_pSelector->SetDefFontSize(fFontSize);
+ }
+ if (m_pUASheet == NULL) {
+ m_pUASheet = LoadDefaultSheetStyle();
+ m_pSelector->SetStyleSheet(FDE_CSSSTYLESHEETGROUP_UserAgent, m_pUASheet);
+ m_pSelector->UpdateStyleIndex(FDE_CSSMEDIATYPE_ALL);
+ }
+}
+IFDE_CSSStyleSheet* CXFA_TextParser::LoadDefaultSheetStyle()
+{
+ static const FX_LPCWSTR s_pStyle = (FX_LPCWSTR)L"html,body,ol,p,ul{display:block}"
+ L"li{display:list-item}"
+ L"ol,ul{padding-left:33px}ol{list-style-type:decimal}ol,ul{margin-top:0;margin-bottom:0}ul,ol{margin:1.12em 0}"
+ L"a{color:#0000ff;text-decoration:underline}b{font-weight:bolder}i{font-style:italic}"
+ L"sup{vertical-align:+15em;font-size:.66em}sub{vertical-align:-15em;font-size:.66em}";
+ return IFDE_CSSStyleSheet::LoadFromBuffer(CFX_WideString(), s_pStyle, FXSYS_wcslen(s_pStyle), FX_CODEPAGE_UTF8);
+}
+IFDE_CSSComputedStyle* CXFA_TextParser::CreateRootStyle(IXFA_TextProvider *pTextProvider)
+{
+ CXFA_Font font = pTextProvider->GetFontNode();
+ CXFA_Para para = pTextProvider->GetParaNode();
+ IFDE_CSSComputedStyle *pStyle = m_pSelector->CreateComputedStyle(NULL);
+ IFDE_CSSFontStyle *pFontStyle = pStyle->GetFontStyles();
+ IFDE_CSSParagraphStyle *pParaStyle = pStyle->GetParagraphStyles();
+ FX_FLOAT fLineHeight = 0, fFontSize = 10;
+ if (para.IsExistInXML()) {
+ fLineHeight = para.GetLineHeight();
+ FDE_CSSLENGTH indent;
+ indent.Set(FDE_CSSLENGTHUNIT_Point, para.GetTextIndent());
+ pParaStyle->SetTextIndent(indent);
+ FDE_CSSTEXTALIGN hAlgin = FDE_CSSTEXTALIGN_Left;
+ switch (para.GetHorizontalAlign()) {
+ case XFA_ATTRIBUTEENUM_Center:
+ hAlgin = FDE_CSSTEXTALIGN_Center;
+ break;
+ case XFA_ATTRIBUTEENUM_Right:
+ hAlgin = FDE_CSSTEXTALIGN_Right;
+ break;
+ case XFA_ATTRIBUTEENUM_Justify:
+ hAlgin = FDE_CSSTEXTALIGN_Justify;
+ break;
+ case XFA_ATTRIBUTEENUM_JustifyAll:
+ hAlgin = FDE_CSSTEXTALIGN_JustifyAll;
+ break;
+ }
+ pParaStyle->SetTextAlign(hAlgin);
+ FDE_CSSRECT rtMarginWidth;
+ rtMarginWidth.left.Set(FDE_CSSLENGTHUNIT_Point, para.GetMarginLeft());
+ rtMarginWidth.top.Set(FDE_CSSLENGTHUNIT_Point, para.GetSpaceAbove());
+ rtMarginWidth.right.Set(FDE_CSSLENGTHUNIT_Point, para.GetMarginRight());
+ rtMarginWidth.bottom.Set(FDE_CSSLENGTHUNIT_Point, para.GetSpaceBelow());
+ pStyle->GetBoundaryStyles()->SetMarginWidth(rtMarginWidth);
+ }
+ if (font.IsExistInXML()) {
+ pFontStyle->SetColor(font.GetColor());
+ pFontStyle->SetFontStyle(font.IsItalic() ? FDE_CSSFONTSTYLE_Italic : FDE_CSSFONTSTYLE_Normal);
+ pFontStyle->SetFontWeight(font.IsBold() ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL);
+ pParaStyle->SetNumberVerticalAlign(-font.GetBaselineShift());
+ fFontSize = font.GetFontSize();
+ FDE_CSSLENGTH letterSpacing;
+ letterSpacing.Set(FDE_CSSLENGTHUNIT_Point, font.GetLetterSpacing());
+ pParaStyle->SetLetterSpacing(letterSpacing);
+ FX_DWORD dwDecoration = 0;
+ if (font.GetLineThrough() > 0) {
+ dwDecoration |= FDE_CSSTEXTDECORATION_LineThrough;
+ }
+ if (font.GetUnderline() > 1) {
+ dwDecoration |= FDE_CSSTEXTDECORATION_Double;
+ } else if (font.GetUnderline() > 0) {
+ dwDecoration |= FDE_CSSTEXTDECORATION_Underline;
+ }
+ pParaStyle->SetTextDecoration(dwDecoration);
+ }
+ pParaStyle->SetLineHeight(fLineHeight);
+ pFontStyle->SetFontSize(fFontSize);
+ return pStyle;
+}
+IFDE_CSSComputedStyle* CXFA_TextParser::CreateStyle(IFDE_CSSComputedStyle *pParentStyle)
+{
+ IFDE_CSSComputedStyle *pNewStyle = m_pSelector->CreateComputedStyle(pParentStyle);
+ FXSYS_assert(pNewStyle != NULL);
+ if (pParentStyle) {
+ IFDE_CSSParagraphStyle *pParaStyle = pParentStyle->GetParagraphStyles();
+ FX_DWORD dwDecoration = pParaStyle->GetTextDecoration();
+ FX_FLOAT fBaseLine = 0;
+ if (pParaStyle->GetVerticalAlign() == FDE_CSSVERTICALALIGN_Number) {
+ fBaseLine = pParaStyle->GetNumberVerticalAlign();
+ }
+ pParaStyle = pNewStyle->GetParagraphStyles();
+ pParaStyle->SetTextDecoration(dwDecoration);
+ pParaStyle->SetNumberVerticalAlign(fBaseLine);
+ IFDE_CSSBoundaryStyle *pBoundarytyle = pParentStyle->GetBoundaryStyles();
+ const FDE_CSSRECT *pRect = pBoundarytyle->GetMarginWidth();
+ if (pRect != NULL) {
+ pBoundarytyle = pNewStyle->GetBoundaryStyles();
+ pBoundarytyle->SetMarginWidth(*pRect);
+ }
+ }
+ return pNewStyle;
+}
+IFDE_CSSComputedStyle* CXFA_TextParser::ComputeStyle(IFDE_XMLNode *pXMLNode, IFDE_CSSComputedStyle *pParentStyle)
+{
+ CXFA_TextParseContext *pContext = (CXFA_TextParseContext*)m_mapXMLNodeToParseContext.GetValueAt(pXMLNode);
+ if (pContext == NULL) {
+ return NULL;
+ }
+ pContext->m_pParentStyle = pParentStyle;
+ CXFA_CSSTagProvider tagProvider;
+ ParseTagInfo(pXMLNode, tagProvider);
+ if (tagProvider.m_bContent) {
+ return NULL;
+ }
+ IFDE_CSSComputedStyle *pStyle = CreateStyle(pParentStyle);
+ IFDE_CSSAccelerator *pCSSAccel = m_pSelector->InitAccelerator();
+ pCSSAccel->OnEnterTag(&tagProvider);
+ m_pSelector->ComputeStyle(&tagProvider, pContext->GetDecls(), pContext->CountDecls(), pStyle);
+ pCSSAccel->OnLeaveTag(&tagProvider);
+ return pStyle;
+}
+void CXFA_TextParser::DoParse(IFDE_XMLNode *pXMLContainer, IXFA_TextProvider *pTextProvider)
+{
+ if (pXMLContainer == NULL || pTextProvider == NULL || m_pAllocator != NULL) {
+ return;
+ }
+ m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Fixed, 32, sizeof(CXFA_CSSTagProvider));
+ InitCSSData(pTextProvider);
+ IFDE_CSSComputedStyle *pRootStyle = CreateRootStyle(pTextProvider);
+ ParseRichText(pXMLContainer, pRootStyle);
+ pRootStyle->Release();
+}
+void CXFA_TextParser::ParseRichText(IFDE_XMLNode *pXMLNode, IFDE_CSSComputedStyle *pParentStyle)
+{
+ if (pXMLNode == NULL) {
+ return;
+ }
+ CXFA_CSSTagProvider tagProvider;
+ ParseTagInfo(pXMLNode, tagProvider);
+ if (!tagProvider.m_bTagAviliable) {
+ return;
+ }
+ IFDE_CSSComputedStyle *pNewStyle = NULL;
+ if ((tagProvider.GetTagName() != FX_WSTRC(L"body")) || (tagProvider.GetTagName() != FX_WSTRC(L"html")) ) {
+ CXFA_TextParseContext *pTextContext = FDE_NewWith(m_pAllocator)CXFA_TextParseContext;
+ FDE_CSSDISPLAY eDisplay = FDE_CSSDISPLAY_Inline;
+ if (!tagProvider.m_bContent) {
+ pNewStyle = CreateStyle(pParentStyle);
+ IFDE_CSSAccelerator *pCSSAccel = m_pSelector->InitAccelerator();
+ pCSSAccel->OnEnterTag(&tagProvider);
+ CFDE_CSSDeclarationArray DeclArray;
+ FX_INT32 iMatchedDecls = m_pSelector->MatchDeclarations(&tagProvider, DeclArray);
+ const IFDE_CSSDeclaration **ppMatchDecls = (const IFDE_CSSDeclaration **)DeclArray.GetData();
+ m_pSelector->ComputeStyle(&tagProvider, ppMatchDecls, iMatchedDecls, pNewStyle);
+ pCSSAccel->OnLeaveTag(&tagProvider);
+ if (iMatchedDecls > 0) {
+ pTextContext->SetDecls(ppMatchDecls, iMatchedDecls);
+ }
+ eDisplay = pNewStyle->GetPositionStyles()->GetDisplay();
+ }
+ pTextContext->SetDisplay(eDisplay);
+ m_mapXMLNodeToParseContext.SetAt(pXMLNode, pTextContext);
+ }
+ for(IFDE_XMLNode *pXMLChild = pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild); pXMLChild; pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ ParseRichText(pXMLChild, pNewStyle);
+ }
+ if (pNewStyle != NULL) {
+ pNewStyle->Release();
+ }
+}
+void CXFA_TextParser::ParseTagInfo(IFDE_XMLNode *pXMLNode, CXFA_CSSTagProvider &tagProvider)
+{
+ static const FX_DWORD s_XFATagName[] = {
+ 0x61,
+ 0x62,
+ 0x69,
+ 0x70,
+ 0x0001f714,
+ 0x00022a55,
+ 0x000239bb,
+ 0x00025881,
+ 0x0bd37faa,
+ 0x0bd37fb8,
+ 0xa73e3af2,
+ 0xb182eaae,
+ 0xdb8ac455,
+ };
+ CFX_WideString wsName;
+ if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+ IFDE_XMLElement *pXMLElement = (IFDE_XMLElement *)pXMLNode;
+ pXMLElement->GetLocalTagName(wsName);
+ tagProvider.SetTagNameObj(wsName);
+ FX_DWORD dwHashCode = FX_HashCode_String_GetW(wsName, wsName.GetLength(), TRUE);
+ static const FX_INT32 s_iCount = sizeof(s_XFATagName) / sizeof(FX_DWORD);
+ CFX_DSPATemplate<FX_DWORD> lookup;
+ tagProvider.m_bTagAviliable = lookup.Lookup(dwHashCode, s_XFATagName, s_iCount) > -1;
+ CFX_WideString wsValue;
+ pXMLElement->GetString(FX_WSTRC(L"style").GetPtr(), wsValue);
+ if (!wsValue.IsEmpty()) {
+ tagProvider.SetAttribute(FX_WSTRC(L"style"), wsValue);
+ }
+ } else if (pXMLNode->GetType() == FDE_XMLNODE_Text) {
+ tagProvider.m_bTagAviliable = TRUE;
+ tagProvider.m_bContent = TRUE;
+ }
+}
+FX_INT32 CXFA_TextParser::GetVAlgin(IXFA_TextProvider *pTextProvider) const
+{
+ FX_INT32 iAlign = XFA_ATTRIBUTEENUM_Top;
+ CXFA_Para para = pTextProvider->GetParaNode();
+ if (para.IsExistInXML()) {
+ iAlign = para.GetVerticalAlign();
+ }
+ return iAlign;
+}
+FX_FLOAT CXFA_TextParser::GetTabInterval(IFDE_CSSComputedStyle *pStyle) const
+{
+ CFX_WideString wsValue;
+ if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"tab-interval"), wsValue)) {
+ CXFA_Measurement ms(wsValue);
+ return ms.ToUnit(XFA_UNIT_Pt);
+ }
+ return 36;
+}
+FX_INT32 CXFA_TextParser::CountTabs(IFDE_CSSComputedStyle *pStyle) const
+{
+ CFX_WideString wsValue;
+ if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"xfa-tab-count"), wsValue)) {
+ return wsValue.GetInteger();
+ }
+ return 0;
+}
+FX_BOOL CXFA_TextParser::IsSpaceRun(IFDE_CSSComputedStyle *pStyle) const
+{
+ CFX_WideString wsValue;
+ if (pStyle && pStyle->GetCustomStyle(FX_WSTRC(L"xfa-spacerun"), wsValue)) {
+ wsValue.MakeLower();
+ return wsValue == FX_WSTRC(L"yes");
+ }
+ return FALSE;
+}
+IFX_Font* CXFA_TextParser::GetFont(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const
+{
+ CFX_WideStringC wsFamily = FX_WSTRC(L"Courier");
+ FX_DWORD dwStyle = 0;
+ CXFA_Font font = pTextProvider->GetFontNode();
+ if (font.IsExistInXML()) {
+ font.GetTypeface(wsFamily);
+ if (font.IsBold()) {
+ dwStyle |= FX_FONTSTYLE_Bold;
+ }
+ if (font.IsItalic()) {
+ dwStyle |= FX_FONTSTYLE_Italic;
+ }
+ }
+ if (pStyle) {
+ IFDE_CSSFontStyle *pFontStyle = pStyle->GetFontStyles();
+ FX_INT32 iCount = pFontStyle->CountFontFamilies();
+ if (iCount > 0) {
+ wsFamily = pFontStyle->GetFontFamily(iCount - 1);
+ }
+ dwStyle = 0;
+ if (pFontStyle->GetFontWeight() > FXFONT_FW_NORMAL) {
+ dwStyle |= FX_FONTSTYLE_Bold;
+ }
+ if (pFontStyle->GetFontStyle() == FDE_CSSFONTSTYLE_Italic) {
+ dwStyle |= FX_FONTSTYLE_Italic;
+ }
+ }
+ CXFA_FFDoc *pDoc = pTextProvider->GetDocNode();
+ FXSYS_assert(pDoc != NULL);
+ CXFA_FontMgr *pFontMgr = pDoc->GetApp()->GetXFAFontMgr();
+ return pFontMgr->GetFont((XFA_HDOC)pDoc, wsFamily, dwStyle);
+}
+FX_FLOAT CXFA_TextParser::GetFontSize(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const
+{
+ if (pStyle != NULL) {
+ return pStyle->GetFontStyles()->GetFontSize();
+ }
+ CXFA_Font font = pTextProvider->GetFontNode();
+ if (font.IsExistInXML()) {
+ return font.GetFontSize();
+ }
+ return 10;
+}
+FX_INT32 CXFA_TextParser::GetHorScale(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, IFDE_XMLNode *pXMLNode) const
+{
+ if (pStyle != NULL) {
+ CFX_WideString wsValue;
+ if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-horizontal-scale"), wsValue)) {
+ return wsValue.GetInteger();
+ }
+ while (pXMLNode) {
+ CXFA_TextParseContext *pContext = (CXFA_TextParseContext*)m_mapXMLNodeToParseContext.GetValueAt(pXMLNode);
+ if (pContext && pContext->m_pParentStyle && pContext->m_pParentStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-horizontal-scale"), wsValue)) {
+ return wsValue.GetInteger();
+ }
+ pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::Parent);
+ }
+ }
+ if (CXFA_Font font = pTextProvider->GetFontNode()) {
+ return (FX_INT32)font.GetHorizontalScale();
+ }
+ return 100;
+}
+FX_INT32 CXFA_TextParser::GetVerScale(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const
+{
+ if (pStyle != NULL) {
+ CFX_WideString wsValue;
+ if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-vertical-scale"), wsValue)) {
+ return wsValue.GetInteger();
+ }
+ }
+ if (CXFA_Font font = pTextProvider->GetFontNode()) {
+ return (FX_INT32)font.GetVerticalScale();
+ }
+ return 100;
+}
+void CXFA_TextParser::GetUnderline(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, FX_INT32 &iUnderline, FX_INT32 &iPeriod) const
+{
+ iUnderline = 0;
+ iPeriod = XFA_ATTRIBUTEENUM_All;
+ if (pStyle) {
+ FX_DWORD dwDecoration = pStyle->GetParagraphStyles()->GetTextDecoration();
+ if (dwDecoration & FDE_CSSTEXTDECORATION_Double) {
+ iUnderline = 2;
+ } else if (dwDecoration & FDE_CSSTEXTDECORATION_Underline) {
+ iUnderline = 1;
+ }
+ CFX_WideString wsValue;
+ if (pStyle->GetCustomStyle(FX_WSTRC(L"underlinePeriod"), wsValue)) {
+ if (wsValue == FX_WSTRC(L"word")) {
+ iPeriod = XFA_ATTRIBUTEENUM_Word;
+ }
+ } else if (CXFA_Font font = pTextProvider->GetFontNode()) {
+ iPeriod = font.GetUnderlinePeriod();
+ }
+ } else {
+ CXFA_Font font = pTextProvider->GetFontNode();
+ if (font.IsExistInXML()) {
+ iUnderline = font.GetUnderline();
+ iPeriod = font.GetUnderlinePeriod();
+ }
+ }
+}
+void CXFA_TextParser::GetLinethrough(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, FX_INT32 &iLinethrough) const
+{
+ if (pStyle) {
+ FX_DWORD dwDecoration = pStyle->GetParagraphStyles()->GetTextDecoration();
+ iLinethrough = (dwDecoration & FDE_CSSTEXTDECORATION_LineThrough) ? 1 : 0;
+ } else {
+ CXFA_Font font = pTextProvider->GetFontNode();
+ if (font.IsExistInXML()) {
+ iLinethrough = font.GetLineThrough();
+ }
+ }
+}
+FX_ARGB CXFA_TextParser::GetColor(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const
+{
+ if (pStyle != NULL) {
+ return pStyle->GetFontStyles()->GetColor();
+ }
+ if (CXFA_Font font = pTextProvider->GetFontNode()) {
+ return font.GetColor();
+ }
+ return 0xFF000000;
+}
+FX_FLOAT CXFA_TextParser::GetBaseline(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle) const
+{
+ if (pStyle != NULL) {
+ IFDE_CSSParagraphStyle *pParaStyle = pStyle->GetParagraphStyles();
+ if (pParaStyle->GetVerticalAlign() == FDE_CSSVERTICALALIGN_Number) {
+ return pParaStyle->GetNumberVerticalAlign();
+ }
+ } else if (CXFA_Font font = pTextProvider->GetFontNode()) {
+ return font.GetBaselineShift();
+ }
+ return 0;
+}
+FX_FLOAT CXFA_TextParser::GetLineHeight(IXFA_TextProvider *pTextProvider, IFDE_CSSComputedStyle *pStyle, FX_BOOL bFirst, FX_FLOAT fVerScale) const
+{
+ FX_FLOAT fLineHeight = 0;
+ if (pStyle != NULL) {
+ fLineHeight = pStyle->GetParagraphStyles()->GetLineHeight();
+ } else if (CXFA_Para para = pTextProvider->GetParaNode()) {
+ fLineHeight = para.GetLineHeight();
+ }
+ if (bFirst) {
+ FX_FLOAT fFontSize = GetFontSize(pTextProvider, pStyle);
+ if (fLineHeight < 0.1f) {
+ fLineHeight = fFontSize;
+ } else {
+ fLineHeight = FX_MIN(fLineHeight, fFontSize);
+ }
+ } else if (fLineHeight < 0.1f) {
+ fLineHeight = GetFontSize(pTextProvider, pStyle) * 1.2f;
+ }
+ fLineHeight *= fVerScale;
+ return fLineHeight;
+}
+FX_BOOL CXFA_TextParser::GetEmbbedObj(IXFA_TextProvider *pTextProvider, IFDE_XMLNode *pXMLNode, CFX_WideString &wsValue)
+{
+ wsValue.Empty();
+ if (pXMLNode == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bRet = FALSE;
+ if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+ IFDE_XMLElement* pElement = (IFDE_XMLElement *)pXMLNode;
+ CFX_WideString wsAttr;
+ pElement->GetString(FX_WSTRC(L"xfa:embed").GetPtr(), wsAttr);
+ if (wsAttr.IsEmpty()) {
+ return FALSE;
+ }
+ if (wsAttr.GetAt(0) == FX_WSTRC(L"#")) {
+ wsAttr.Delete(0);
+ }
+ CFX_WideString ws;
+ pElement->GetString(FX_WSTRC(L"xfa:embedType").GetPtr(), ws);
+ if (ws.IsEmpty()) {
+ ws = L"som";
+ } else {
+ ws.MakeLower();
+ }
+ FX_BOOL bURI = (ws == FX_WSTRC(L"uri"));
+ if (!bURI && ws != FX_WSTRC(L"som")) {
+ return FALSE;
+ }
+ ws.Empty();
+ pElement->GetString(FX_WSTRC(L"xfa:embedMode").GetPtr(), ws);
+ if (ws.IsEmpty()) {
+ ws = L"formatted";
+ } else {
+ ws.MakeLower();
+ }
+ FX_BOOL bRaw = (ws == FX_WSTRC(L"raw"));
+ if (!bRaw && ws != FX_WSTRC(L"formatted")) {
+ return FALSE;
+ }
+ bRet = pTextProvider->GetEmbbedObj(bURI, bRaw, wsAttr, wsValue);
+ }
+ return bRet;
+}
+CXFA_TextParseContext* CXFA_TextParser::GetParseContextFromMap(IFDE_XMLNode *pXMLNode)
+{
+ return (CXFA_TextParseContext*)m_mapXMLNodeToParseContext.GetValueAt(pXMLNode);
+}
+enum XFA_TABSTOPSSTATUS {
+ XFA_TABSTOPSSTATUS_Error,
+ XFA_TABSTOPSSTATUS_EOS,
+ XFA_TABSTOPSSTATUS_None,
+ XFA_TABSTOPSSTATUS_Alignment,
+ XFA_TABSTOPSSTATUS_StartLeader,
+ XFA_TABSTOPSSTATUS_Leader,
+ XFA_TABSTOPSSTATUS_Location,
+};
+FX_BOOL CXFA_TextParser::GetTabstops(IFDE_CSSComputedStyle *pStyle, CXFA_TextTabstopsContext *pTabstopContext)
+{
+ if (pStyle == NULL || pTabstopContext == NULL) {
+ return FALSE;
+ }
+ CFX_WideString wsValue;
+ if (!pStyle->GetCustomStyle(FX_WSTRC(L"xfa-tab-stops"), wsValue)
+ && !pStyle->GetCustomStyle(FX_WSTRC(L"tab-stops"), wsValue)) {
+ return FALSE;
+ }
+ FX_INT32 iLength = wsValue.GetLength();
+ FX_LPCWSTR pTabStops = wsValue;
+ FX_INT32 iCur = 0;
+ FX_INT32 iLast = 0;
+ CFX_WideString wsAlign;
+ XFA_TABSTOPSSTATUS eStatus = XFA_TABSTOPSSTATUS_None;
+ FX_WCHAR ch;
+ while (iCur < iLength) {
+ ch = pTabStops[iCur];
+ switch (eStatus) {
+ case XFA_TABSTOPSSTATUS_None:
+ if (ch <= ' ') {
+ iCur++;
+ } else {
+ eStatus = XFA_TABSTOPSSTATUS_Alignment;
+ iLast = iCur;
+ }
+ break;
+ case XFA_TABSTOPSSTATUS_Alignment:
+ if (ch == ' ') {
+ wsAlign = CFX_WideStringC(pTabStops + iLast, iCur - iLast);
+ eStatus = XFA_TABSTOPSSTATUS_StartLeader;
+ iCur++;
+ while (iCur < iLength && pTabStops[iCur] <= ' ') {
+ iCur++;
+ }
+ iLast = iCur;
+ } else {
+ iCur++;
+ }
+ break;
+ case XFA_TABSTOPSSTATUS_StartLeader:
+ if (ch != 'l') {
+ eStatus = XFA_TABSTOPSSTATUS_Location;
+ } else {
+ FX_INT32 iCount = 0;
+ while (iCur < iLength) {
+ ch = pTabStops[iCur];
+ iCur++;
+ if (ch == '(') {
+ iCount++;
+ } else if (ch == ')') {
+ iCount--;
+ if (iCount == 0) {
+ break;
+ }
+ }
+ }
+ while (iCur < iLength && pTabStops[iCur] <= ' ') {
+ iCur++;
+ }
+ iLast = iCur;
+ eStatus = XFA_TABSTOPSSTATUS_Location;
+ }
+ break;
+ case XFA_TABSTOPSSTATUS_Location:
+ if (ch == ' ') {
+ FX_DWORD dwHashCode = FX_HashCode_String_GetW(wsAlign, wsAlign.GetLength(), TRUE);
+ CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast));
+ FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt);
+ pTabstopContext->Append(dwHashCode, fPos);
+ wsAlign.Empty();
+ eStatus = XFA_TABSTOPSSTATUS_None;
+ }
+ iCur++;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!wsAlign.IsEmpty()) {
+ FX_DWORD dwHashCode = FX_HashCode_String_GetW(wsAlign, wsAlign.GetLength(), TRUE);
+ CXFA_Measurement ms(CFX_WideStringC(pTabStops + iLast, iCur - iLast));
+ FX_FLOAT fPos = ms.ToUnit(XFA_UNIT_Pt);
+ pTabstopContext->Append(dwHashCode, fPos);
+ }
+ return TRUE;
+}
+CXFA_TextLayout::CXFA_TextLayout(IXFA_TextProvider *pTextProvider)
+ : m_pTextProvider(pTextProvider)
+ , m_pTextDataNode(NULL)
+ , m_pAllocator(NULL)
+ , m_pBreak(NULL)
+ , m_dwTextData(0)
+ , m_pLoader(NULL)
+ , m_iLines(0)
+ , m_fMaxWidth(0)
+ , m_pTabstopContext(NULL)
+ , m_bBlockContinue(TRUE)
+ , m_bRichText(FALSE)
+ , m_bHasBlock(FALSE)
+{
+ FXSYS_assert(m_pTextProvider != NULL);
+}
+CXFA_TextLayout::~CXFA_TextLayout()
+{
+ m_textParser.Reset();
+ if (m_pLoader != NULL) {
+ delete m_pLoader;
+ }
+ if (m_pTabstopContext != NULL) {
+ delete m_pTabstopContext;
+ }
+ Unload();
+}
+void CXFA_TextLayout::Unload()
+{
+ FX_INT32 iCount = m_pieceLines.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i++) {
+ CXFA_PieceLine *pLine = m_pieceLines.GetAt(i);
+ FDE_DeleteWith(CXFA_PieceLine, m_pAllocator, pLine);
+ }
+ m_pieceLines.RemoveAll();
+ if (m_pBreak != NULL) {
+ m_pBreak->Release();
+ m_pBreak = NULL;
+ }
+ if (m_pAllocator != NULL) {
+ m_pAllocator->Release();
+ m_pAllocator = NULL;
+ }
+}
+const CXFA_PieceLineArray* CXFA_TextLayout::GetPieceLines()
+{
+ return &m_pieceLines;
+}
+void CXFA_TextLayout::GetTextDataNode()
+{
+ if (m_pTextProvider == NULL) {
+ return;
+ }
+ CXFA_Node *pNode = m_pTextProvider->GetTextNode(m_bRichText);
+ if (pNode && m_bRichText) {
+ m_textParser.Reset();
+ }
+ m_pTextDataNode = pNode;
+}
+IFDE_XMLNode* CXFA_TextLayout::GetXMLContainerNode()
+{
+ IFDE_XMLNode* pXMLContainer = NULL;
+ if (m_bRichText) {
+ IFDE_XMLNode *pXMLRoot = m_pTextDataNode->GetXMLMappingNode();
+ if (!pXMLRoot) {
+ return pXMLContainer;
+ }
+ for (IFDE_XMLNode *pXMLChild = pXMLRoot->GetNodeItem(IFDE_XMLNode::FirstChild); pXMLChild; pXMLChild = pXMLChild->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ if (pXMLChild->GetType() == FDE_XMLNODE_Element) {
+ IFDE_XMLElement *pXMLElement = (IFDE_XMLElement*)pXMLChild;
+ CFX_WideString wsTag;
+ pXMLElement->GetLocalTagName(wsTag);
+ if (wsTag.Equal(FX_WSTRC(L"body")) || wsTag.Equal(FX_WSTRC(L"html"))) {
+ pXMLContainer = pXMLChild;
+ break;
+ }
+ }
+ }
+ }
+ return pXMLContainer;
+}
+IFX_RTFBreak* CXFA_TextLayout::CreateBreak(FX_BOOL bDefault)
+{
+ FX_DWORD dwStyle = FX_RTFLAYOUTSTYLE_ExpandTab;
+ if (!bDefault) {
+ dwStyle |= FX_RTFLAYOUTSTYLE_Pagination;
+ }
+ IFX_RTFBreak *pBreak = IFX_RTFBreak::Create(0);
+ pBreak->SetLayoutStyles(dwStyle);
+ pBreak->SetLineBreakChar(L'\n');
+ pBreak->SetLineBreakTolerance(1);
+ pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, NULL));
+ pBreak->SetFontSize(m_textParser.GetFontSize(m_pTextProvider, NULL));
+ return pBreak;
+}
+void CXFA_TextLayout::InitBreak(FX_FLOAT fLineWidth)
+{
+ CXFA_Font font = m_pTextProvider->GetFontNode();
+ CXFA_Para para = m_pTextProvider->GetParaNode();
+ FX_FLOAT fStart = 0;
+ FX_FLOAT fStartPos = 0;
+ if (para.IsExistInXML()) {
+ FX_INT32 iAlign = FX_RTFLINEALIGNMENT_Left;
+ switch (para.GetHorizontalAlign()) {
+ case XFA_ATTRIBUTEENUM_Center:
+ iAlign = FX_RTFLINEALIGNMENT_Center;
+ break;
+ case XFA_ATTRIBUTEENUM_Right:
+ iAlign = FX_RTFLINEALIGNMENT_Right;
+ break;
+ case XFA_ATTRIBUTEENUM_Justify:
+ iAlign = FX_RTFLINEALIGNMENT_Justified;
+ break;
+ case XFA_ATTRIBUTEENUM_JustifyAll:
+ iAlign = FX_RTFLINEALIGNMENT_Distributed;
+ break;
+ }
+ m_pBreak->SetAlignment(iAlign);
+ fStart = para.GetMarginLeft();
+ if (m_pTextProvider->IsCheckButtonAndAutoWidth()) {
+ if (iAlign != FX_RTFLINEALIGNMENT_Left) {
+ fLineWidth -= para.GetMarginRight();
+ }
+ } else {
+ fLineWidth -= para.GetMarginRight();
+ }
+ if (fLineWidth < 0) {
+ fLineWidth = fStart;
+ }
+ fStartPos = fStart;
+ FX_FLOAT fIndent = para.GetTextIndent();
+ if (fIndent > 0) {
+ fStartPos += fIndent;
+ }
+ }
+ m_pBreak->SetLineWidth(fStart, fLineWidth);
+ m_pBreak->SetLinePos(fStartPos);
+ if (font.IsExistInXML()) {
+ m_pBreak->SetHorizontalScale((FX_INT32)font.GetHorizontalScale());
+ m_pBreak->SetVerticalScale((FX_INT32)font.GetVerticalScale());
+ m_pBreak->SetCharSpace(font.GetLetterSpacing());
+ }
+ FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, NULL);
+ m_pBreak->SetFontSize(fFontSize);
+ m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, NULL));
+ m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f);
+}
+void CXFA_TextLayout::InitBreak(IFDE_CSSComputedStyle *pStyle, FDE_CSSDISPLAY eDisplay, FX_FLOAT fLineWidth, IFDE_XMLNode *pXMLNode, IFDE_CSSComputedStyle *pParentStyle)
+{
+ if (pStyle == NULL) {
+ InitBreak(fLineWidth);
+ return;
+ }
+ IFDE_CSSParagraphStyle *pParaStyle = pStyle->GetParagraphStyles();
+ if (eDisplay == FDE_CSSDISPLAY_Block || eDisplay == FDE_CSSDISPLAY_ListItem) {
+ FX_INT32 iAlign = FX_RTFLINEALIGNMENT_Left;
+ switch (pParaStyle->GetTextAlign()) {
+ case FDE_CSSTEXTALIGN_Right:
+ iAlign = FX_RTFLINEALIGNMENT_Right;
+ break;
+ case FDE_CSSTEXTALIGN_Center:
+ iAlign = FX_RTFLINEALIGNMENT_Center;
+ break;
+ case FDE_CSSTEXTALIGN_Justify:
+ iAlign = FX_RTFLINEALIGNMENT_Justified;
+ break;
+ case FDE_CSSTEXTALIGN_JustifyAll:
+ iAlign = FX_RTFLINEALIGNMENT_Distributed;
+ break;
+ default:
+ break;
+ }
+ m_pBreak->SetAlignment(iAlign);
+ FX_FLOAT fStart = 0;
+ const FDE_CSSRECT *pRect = pStyle->GetBoundaryStyles()->GetMarginWidth();
+ const FDE_CSSRECT *pPaddingRect = pStyle->GetBoundaryStyles()->GetPaddingWidth();
+ if (pRect != NULL) {
+ fStart = pRect->left.GetValue();
+ fLineWidth -= pRect->right.GetValue();
+ if (pPaddingRect != NULL) {
+ fStart += pPaddingRect->left.GetValue();
+ fLineWidth -= pPaddingRect->right.GetValue();
+ }
+ if (eDisplay == FDE_CSSDISPLAY_ListItem) {
+ const FDE_CSSRECT *pParRect = pParentStyle->GetBoundaryStyles()->GetMarginWidth();
+ const FDE_CSSRECT *pParPaddingRect = pParentStyle->GetBoundaryStyles()->GetPaddingWidth();
+ if (pParRect != NULL) {
+ fStart += pParRect->left.GetValue();
+ fLineWidth -= pParRect->right.GetValue();
+ if (pParPaddingRect != NULL) {
+ fStart += pParPaddingRect->left.GetValue();
+ fLineWidth -= pParPaddingRect->right.GetValue();
+ }
+ }
+ FDE_CSSRECT pNewRect;
+ pNewRect.left.Set(FDE_CSSLENGTHUNIT_Point, fStart);
+ pNewRect.right.Set(FDE_CSSLENGTHUNIT_Point, pRect->right.GetValue());
+ pNewRect.top.Set(FDE_CSSLENGTHUNIT_Point, pRect->top.GetValue());
+ pNewRect.bottom.Set(FDE_CSSLENGTHUNIT_Point, pRect->bottom.GetValue());
+ pStyle->GetBoundaryStyles()->SetMarginWidth(pNewRect);
+ }
+ }
+ m_pBreak->SetLineWidth(fStart, fLineWidth);
+ FX_FLOAT fIndent = pParaStyle->GetTextIndent().GetValue();
+ if (fIndent > 0) {
+ fStart += fIndent;
+ }
+ m_pBreak->SetLinePos(fStart);
+ m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle));
+ if (m_pTabstopContext == NULL) {
+ m_pTabstopContext = FX_NEW CXFA_TextTabstopsContext;
+ }
+ m_textParser.GetTabstops(pStyle, m_pTabstopContext);
+ for (FX_INT32 i = 0; i < m_pTabstopContext->m_iTabCount; i++) {
+ XFA_TABSTOPS *pTab = m_pTabstopContext->m_tabstops.GetDataPtr(i);
+ m_pBreak->AddPositionedTab(pTab->fTabstops);
+ }
+ }
+ FX_FLOAT fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle);
+ m_pBreak->SetFontSize(fFontSize);
+ m_pBreak->SetLineBreakTolerance(fFontSize * 0.2f);
+ m_pBreak->SetFont(m_textParser.GetFont(m_pTextProvider, pStyle));
+ m_pBreak->SetHorizontalScale(m_textParser.GetHorScale(m_pTextProvider, pStyle, pXMLNode));
+ m_pBreak->SetVerticalScale(m_textParser.GetVerScale(m_pTextProvider, pStyle));
+ m_pBreak->SetCharSpace(pParaStyle->GetLetterSpacing().GetValue());
+}
+FX_INT32 CXFA_TextLayout::GetText(CFX_WideString &wsText)
+{
+ GetTextDataNode();
+ wsText.Empty();
+ if (m_bRichText) {
+ } else {
+ wsText = m_pTextDataNode->GetContent();
+ }
+ return wsText.GetLength();
+}
+FX_FLOAT CXFA_TextLayout::GetLayoutHeight()
+{
+ if (m_pLoader == NULL) {
+ return 0;
+ }
+ FX_INT32 iCount = m_pLoader->m_lineHeights.GetSize();
+ if (iCount == 0 && m_pLoader->m_fWidth > 0) {
+ CFX_SizeF szMax, szDef;
+ szMax.Set(m_pLoader->m_fWidth, m_pLoader->m_fHeight);
+ szDef.Set(0, 0);
+ m_pLoader->m_bSaveLineHeight = TRUE;
+ m_pLoader->m_fLastPos = 0;
+ CalcSize(szMax, szMax, szDef);
+ m_pLoader->m_bSaveLineHeight = FALSE;
+ return szDef.y;
+ }
+ FX_FLOAT fHeight = m_pLoader->m_fHeight;
+ if (fHeight < 0.1f) {
+ fHeight = 0;
+ for (FX_INT32 i = 0; i < iCount; i++) {
+ fHeight += m_pLoader->m_lineHeights.ElementAt(i);
+ }
+ }
+ return fHeight;
+}
+FX_FLOAT CXFA_TextLayout::StartLayout(FX_FLOAT fWidth )
+{
+ if (m_pLoader == NULL) {
+ m_pLoader = FX_NEW CXFA_LoaderContext;
+ }
+ if (fWidth < 0 || (m_pLoader->m_fWidth > -1 && FXSYS_fabs(fWidth - m_pLoader->m_fWidth) > 0)) {
+ m_pLoader->m_lineHeights.RemoveAll();
+ m_Blocks.RemoveAll();
+ Unload();
+ m_pLoader->m_fStartLineOffset = 0;
+ }
+ m_pLoader->m_fWidth = fWidth;
+ if (fWidth < 0) {
+ CFX_SizeF szMax, szDef;
+ szMax.Set(0, 0);
+ szDef.Set(0, 0);
+ m_pLoader->m_bSaveLineHeight = TRUE;
+ m_pLoader->m_fLastPos = 0;
+ CalcSize(szMax, szMax, szDef);
+ m_pLoader->m_bSaveLineHeight = FALSE;
+ fWidth = szDef.x;
+ }
+ return fWidth;
+}
+FX_BOOL CXFA_TextLayout::DoLayout(FX_INT32 iBlockIndex, FX_FLOAT &fCalcHeight, FX_FLOAT fContentAreaHeight , FX_FLOAT fTextHeight )
+{
+ if (m_pLoader == NULL) {
+ return FALSE;
+ }
+ FX_INT32 iBlockCount = m_Blocks.GetSize();
+ FX_FLOAT fHeight = fTextHeight;
+ if (fHeight < 0) {
+ fHeight = GetLayoutHeight();
+ }
+ m_pLoader->m_fHeight = fHeight;
+ if (fContentAreaHeight < 0) {
+ return FALSE;
+ }
+ m_bHasBlock = TRUE;
+ if (iBlockCount == 0 && fHeight > 0) {
+ fHeight = fTextHeight - GetLayoutHeight();
+ if (fHeight > 0) {
+ FX_INT32 iAlign = m_textParser.GetVAlgin(m_pTextProvider);
+ if (iAlign == XFA_ATTRIBUTEENUM_Middle) {
+ fHeight /= 2.0f;
+ } else if (iAlign != XFA_ATTRIBUTEENUM_Bottom) {
+ fHeight = 0;
+ }
+ m_pLoader->m_fStartLineOffset = fHeight;
+ }
+ }
+ FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset;
+ FX_INT32 iLineIndex = 0;
+ if (iBlockCount > 1) {
+ if (iBlockCount >= (iBlockIndex + 1) * 2) {
+ iLineIndex = m_Blocks.ElementAt(iBlockIndex * 2);
+ } else {
+ iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) + m_Blocks.ElementAt(iBlockCount - 2);
+ }
+ if (m_pLoader->m_BlocksHeight.GetSize() > 0) {
+ for (FX_INT32 i = 0; i < iBlockIndex; i++) {
+ fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
+ }
+ }
+ }
+ FX_INT32 iCount = m_pLoader->m_lineHeights.GetSize();
+ FX_INT32 i = 0;
+ for (i = iLineIndex; i < iCount; i++) {
+ FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i);
+ if ((i == iLineIndex) && (fLineHeight - fContentAreaHeight > 0.001)) {
+ fCalcHeight = 0;
+ return TRUE;
+ }
+ if (fLinePos + fLineHeight - fContentAreaHeight > 0.001) {
+ if (iBlockCount >= (iBlockIndex + 1) * 2) {
+ m_Blocks.SetAt(iBlockIndex * 2, iLineIndex);
+ m_Blocks.SetAt(iBlockIndex * 2 + 1, i - iLineIndex);
+ } else {
+ m_Blocks.Add(iLineIndex);
+ m_Blocks.Add(i - iLineIndex);
+ }
+ if (i == iLineIndex) {
+ if (fCalcHeight <= fLinePos) {
+ if (m_pLoader->m_BlocksHeight.GetSize() > iBlockIndex * 2 && (m_pLoader->m_BlocksHeight.GetAt(iBlockIndex * 2) == iBlockIndex)) {
+ m_pLoader->m_BlocksHeight.SetAt(iBlockIndex * 2 + 1, fCalcHeight);
+ } else {
+ m_pLoader->m_BlocksHeight.Add((FX_FLOAT)iBlockIndex);
+ m_pLoader->m_BlocksHeight.Add(fCalcHeight);
+ }
+ }
+ return TRUE;
+ }
+ fCalcHeight = fLinePos;
+ return TRUE;
+ }
+ fLinePos += fLineHeight;
+ }
+ return FALSE;
+}
+FX_INT32 CXFA_TextLayout::CountBlocks() const
+{
+ FX_INT32 iCount = m_Blocks.GetSize() / 2;
+ return iCount > 0 ? iCount : 1;
+}
+FX_BOOL CXFA_TextLayout::CalcSize(const CFX_SizeF &minSize, const CFX_SizeF &maxSize, CFX_SizeF &defaultSize)
+{
+ defaultSize.x = maxSize.x;
+ if (defaultSize.x < 1) {
+ defaultSize.x = 0xFFFF;
+ }
+ if (m_pBreak != NULL) {
+ m_pBreak->Release();
+ }
+ m_pBreak = CreateBreak(FALSE);
+ FX_FLOAT fLinePos = 0;
+ m_iLines = 0;
+ m_fMaxWidth = 0;
+ Loader(defaultSize, fLinePos, FALSE);
+ if (fLinePos < 0.1f) {
+ fLinePos = m_textParser.GetFontSize(m_pTextProvider, NULL);
+ }
+ if (m_pTabstopContext) {
+ delete m_pTabstopContext;
+ m_pTabstopContext = NULL;
+ }
+ defaultSize.Set(m_fMaxWidth, fLinePos);
+ return TRUE;
+}
+FX_BOOL CXFA_TextLayout::Layout(const CFX_SizeF &size, FX_FLOAT* fHeight)
+{
+ if (size.x < 1) {
+ return FALSE;
+ }
+ Unload();
+ m_pBreak = CreateBreak(TRUE);
+ if (m_pLoader != NULL) {
+ m_pLoader->m_iTotalLines = -1;
+ m_pLoader->m_iChar = 0;
+ }
+ m_iLines = 0;
+ FX_FLOAT fLinePos = 0;
+ Loader(size, fLinePos, TRUE);
+ UpdateAlign(size.y, fLinePos);
+ if (m_pTabstopContext) {
+ delete m_pTabstopContext;
+ m_pTabstopContext = NULL;
+ }
+ if (fHeight) {
+ *fHeight = fLinePos;
+ }
+ return TRUE;
+}
+FX_BOOL CXFA_TextLayout::Layout(FX_INT32 iBlock)
+{
+ if (m_pLoader == NULL || iBlock < 0 || iBlock >= CountBlocks()) {
+ return FALSE;
+ }
+ if (m_pLoader->m_fWidth < 1) {
+ return FALSE;
+ }
+ m_pLoader->m_iTotalLines = -1;
+ m_iLines = 0;
+ FX_FLOAT fLinePos = 0;
+ CXFA_Node *pNode = NULL;
+ CFX_SizeF szText;
+ szText.Set(m_pLoader->m_fWidth, m_pLoader->m_fHeight);
+ FX_INT32 iCount = m_Blocks.GetSize();
+ FX_INT32 iBlocksHeightCount = m_pLoader->m_BlocksHeight.GetSize();
+ iBlocksHeightCount /= 2;
+ if (iBlock < iBlocksHeightCount) {
+ return TRUE;
+ }
+ if (iBlock == iBlocksHeightCount) {
+ Unload();
+ m_pBreak = CreateBreak(TRUE);
+ fLinePos = m_pLoader->m_fStartLineOffset;
+ for (FX_INT32 i = 0; i < iBlocksHeightCount; i++) {
+ fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
+ }
+ m_pLoader->m_iChar = 0;
+ if (iCount > 1) {
+ m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock * 2 + 1);
+ }
+ Loader(szText, fLinePos, TRUE);
+ if (iCount == 0 && m_pLoader->m_fStartLineOffset < 0.1f) {
+ UpdateAlign(szText.y, fLinePos);
+ }
+ } else if (m_pTextDataNode != NULL) {
+ iBlock *= 2;
+ if (iBlock < iCount - 2) {
+ m_pLoader->m_iTotalLines = m_Blocks.ElementAt(iBlock + 1);
+ }
+ m_pBreak->Reset();
+ if (m_bRichText) {
+ IFDE_XMLNode* pContainerNode = GetXMLContainerNode();
+ if (!pContainerNode) {
+ return TRUE;
+ }
+ IFDE_XMLNode *pXMLNode = m_pLoader->m_pXMLNode;
+ if (pXMLNode == NULL) {
+ return TRUE;
+ }
+ IFDE_XMLNode* pSaveXMLNode = m_pLoader->m_pXMLNode;
+ for (; pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle, TRUE);
+ if (!bFlag) {
+ break;
+ }
+ }
+ while (pXMLNode == NULL) {
+ pXMLNode = pSaveXMLNode->GetNodeItem(IFDE_XMLNode::Parent);
+ if (pXMLNode == pContainerNode) {
+ break;
+ }
+ FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle, TRUE, NULL , FALSE);
+ if (!bFlag) {
+ break;
+ }
+ pSaveXMLNode = pXMLNode;
+ pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling);
+ if (!pXMLNode) {
+ continue;
+ }
+ for (; pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ FX_BOOL bFlag = LoadRichText(pXMLNode, szText, fLinePos, m_pLoader->m_pParentStyle, TRUE);
+ if (!bFlag) {
+ break;
+ }
+ }
+ }
+ } else {
+ pNode = m_pLoader->m_pNode;
+ if (pNode == NULL) {
+ return TRUE;
+ }
+ LoadText(pNode, szText, fLinePos, TRUE);
+ }
+ }
+ if (iBlock == iCount) {
+ if (m_pTabstopContext != NULL) {
+ delete m_pTabstopContext;
+ m_pTabstopContext = NULL;
+ }
+ if (m_pLoader != NULL) {
+ delete m_pLoader;
+ m_pLoader = NULL;
+ }
+ }
+ return TRUE;
+}
+void CXFA_TextLayout::ItemBlocks(const CFX_RectF& rtText, FX_INT32 iBlockIndex)
+{
+ if (!m_pLoader) {
+ return;
+ }
+ FX_INT32 iCountHeight = m_pLoader->m_lineHeights.GetSize();
+ if (iCountHeight == 0) {
+ return;
+ }
+ FX_BOOL bEndItem = TRUE;
+ FX_INT32 iBlockCount = m_Blocks.GetSize();
+ FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset;
+ FX_INT32 iLineIndex = 0;
+ if (iBlockIndex > 0) {
+ FX_INT32 iBlockHeightCount = m_pLoader->m_BlocksHeight.GetSize();
+ iBlockHeightCount /= 2;
+ if (iBlockHeightCount >= iBlockIndex) {
+ for (FX_INT32 i = 0; i < iBlockIndex; i++) {
+ fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
+ }
+ } else {
+ fLinePos = 0;
+ }
+ iLineIndex = m_Blocks.ElementAt(iBlockCount - 1) + m_Blocks.ElementAt(iBlockCount - 2);
+ }
+ FX_INT32 i = 0;
+ for (i = iLineIndex; i < iCountHeight; i++) {
+ FX_FLOAT fLineHeight = m_pLoader->m_lineHeights.ElementAt(i);
+ if (fLinePos + fLineHeight - rtText.height > 0.001) {
+ m_Blocks.Add(iLineIndex);
+ m_Blocks.Add(i - iLineIndex);
+ bEndItem = FALSE;
+ break;
+ }
+ fLinePos += fLineHeight;
+ }
+ if (iCountHeight > 0 && (i - iLineIndex) > 0 && bEndItem) {
+ m_Blocks.Add(iLineIndex);
+ m_Blocks.Add(i - iLineIndex);
+ }
+}
+FX_BOOL CXFA_TextLayout::DrawString(CFX_RenderDevice *pFxDevice, const CFX_Matrix &tmDoc2Device, const CFX_RectF &rtClip, FX_INT32 iBlock )
+{
+ IFDE_RenderDevice *pDevice = IFDE_RenderDevice::Create(pFxDevice);
+ if (pDevice == NULL) {
+ return FALSE;
+ }
+ FDE_HDEVICESTATE state = pDevice->SaveState();
+ pDevice->SetClipRect(rtClip);
+ IFDE_SolidBrush *pSolidBrush = (IFDE_SolidBrush*)IFDE_Brush::Create(FDE_BRUSHTYPE_Solid);
+ IFDE_Pen *pPen = IFDE_Pen::Create();
+ FXSYS_assert(pDevice != NULL && pSolidBrush != NULL && pPen != NULL);
+ if (m_pieceLines.GetSize() == 0) {
+ FX_INT32 iBlockCount = CountBlocks();
+ for (FX_INT32 i = 0; i < iBlockCount; i++) {
+ Layout(i);
+ }
+ }
+ FXTEXT_CHARPOS *pCharPos = NULL;
+ FX_INT32 iCharCount = 0;
+ FX_INT32 iLineStart = 0;
+ FX_INT32 iPieceLines = m_pieceLines.GetSize();
+ FX_INT32 iCount = m_Blocks.GetSize();
+ if (iCount > 0) {
+ iBlock *= 2;
+ if (iBlock < iCount) {
+ iLineStart = m_Blocks.ElementAt(iBlock);
+ iPieceLines = m_Blocks.ElementAt(iBlock + 1);
+ } else {
+ iPieceLines = 0;
+ }
+ }
+ for (FX_INT32 i = 0; i < iPieceLines; i++) {
+ if(i + iLineStart >= m_pieceLines.GetSize()) {
+ break;
+ }
+ CXFA_PieceLine *pPieceLine = m_pieceLines.GetAt(i + iLineStart);
+ FX_INT32 iPieces = pPieceLine->m_textPieces.GetSize();
+ FX_INT32 j = 0;
+ for (j = 0; j < iPieces; j++) {
+ XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
+ FX_INT32 iChars = pPiece->iChars;
+ if (iCharCount < iChars) {
+ if (pCharPos != NULL) {
+ FDE_Free(pCharPos);
+ }
+ pCharPos = (FXTEXT_CHARPOS*)FDE_Alloc(iChars * sizeof(FXTEXT_CHARPOS));
+ iCharCount = iChars;
+ }
+ FXSYS_memset(pCharPos, 0, iCharCount * sizeof(FXTEXT_CHARPOS));
+ RenderString(pDevice, pSolidBrush, pPieceLine, j, pCharPos, tmDoc2Device);
+ }
+ for (j = 0; j < iPieces; j++) {
+ RenderPath(pDevice, pPen, pPieceLine, j, pCharPos, tmDoc2Device);
+ }
+ }
+ pDevice->RestoreState(state);
+ if (pCharPos != NULL) {
+ FDE_Free(pCharPos);
+ }
+ pSolidBrush->Release();
+ pPen->Release();
+ pDevice->Release();
+ return iPieceLines;
+}
+void CXFA_TextLayout::UpdateAlign(FX_FLOAT fHeight, FX_FLOAT fBottom)
+{
+ fHeight -= fBottom;
+ if (fHeight < 0.1f) {
+ return;
+ }
+ switch (m_textParser.GetVAlgin(m_pTextProvider)) {
+ case XFA_ATTRIBUTEENUM_Middle:
+ fHeight /= 2.0f;
+ break;
+ case XFA_ATTRIBUTEENUM_Bottom:
+ break;
+ default:
+ return;
+ }
+ FX_INT32 iCount = m_pieceLines.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i++) {
+ CXFA_PieceLine *pPieceLine = m_pieceLines.GetAt(i);
+ FX_INT32 iPieces = pPieceLine->m_textPieces.GetSize();
+ for (FX_INT32 j = 0; j < iPieces; j++) {
+ XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
+ CFX_RectF &rect = pPiece->rtPiece;
+ rect.top += fHeight;
+ }
+ }
+}
+FX_BOOL CXFA_TextLayout::Loader(const CFX_SizeF &szText, FX_FLOAT &fLinePos, FX_BOOL bSavePieces )
+{
+ if (m_pAllocator == NULL) {
+ m_pAllocator = FX_CreateAllocator(FX_ALLOCTYPE_Static, 256, 0);
+ }
+ GetTextDataNode();
+ if (m_pTextDataNode == NULL) {
+ return TRUE;
+ }
+ if (m_bRichText) {
+ IFDE_XMLNode *pXMLContainer = GetXMLContainerNode();
+ if (pXMLContainer) {
+ if (!m_textParser.IsParsed()) {
+ m_textParser.DoParse(pXMLContainer, m_pTextProvider);
+ }
+ IFDE_CSSComputedStyle *pRootStyle = m_textParser.CreateRootStyle(m_pTextProvider);
+ LoadRichText(pXMLContainer, szText, fLinePos, pRootStyle, bSavePieces);
+ pRootStyle->Release();
+ }
+ } else {
+ LoadText(m_pTextDataNode, szText, fLinePos, bSavePieces);
+ }
+ return TRUE;
+}
+void CXFA_TextLayout::LoadText(CXFA_Node *pNode, const CFX_SizeF &szText, FX_FLOAT &fLinePos, FX_BOOL bSavePieces)
+{
+ InitBreak(szText.x);
+ CXFA_Para para = m_pTextProvider->GetParaNode();
+ FX_FLOAT fSpaceAbove = 0;
+ if (para.IsExistInXML()) {
+ fSpaceAbove = para.GetSpaceAbove();
+ if (fSpaceAbove < 0.1f) {
+ fSpaceAbove = 0;
+ }
+ FX_INT32 verAlign = para.GetVerticalAlign();
+ switch (verAlign) {
+ case XFA_ATTRIBUTEENUM_Top:
+ case XFA_ATTRIBUTEENUM_Middle:
+ case XFA_ATTRIBUTEENUM_Bottom: {
+ fLinePos += fSpaceAbove;
+ break;
+ }
+ }
+ }
+ CFX_WideString wsText = pNode->GetContent();
+ wsText.TrimRight(L" ");
+ FX_BOOL bRet = AppendChar(wsText, fLinePos, fSpaceAbove, bSavePieces);
+ if (bRet && m_pLoader != NULL) {
+ m_pLoader->m_pNode = pNode;
+ } else {
+ EndBreak(FX_RTFBREAK_ParagraphBreak, fLinePos, bSavePieces);
+ }
+}
+FX_BOOL CXFA_TextLayout::LoadRichText(IFDE_XMLNode *pXMLNode, const CFX_SizeF &szText, FX_FLOAT &fLinePos, IFDE_CSSComputedStyle *pParentStyle, FX_BOOL bSavePieces, CXFA_LinkUserData* pLinkData, FX_BOOL bEndBreak, FX_BOOL bIsOl, FX_INT32 iLiCount)
+{
+ if (pXMLNode == NULL) {
+ return FALSE;
+ }
+ CXFA_TextParseContext *pContext = m_textParser.GetParseContextFromMap(pXMLNode);
+ FDE_CSSDISPLAY eDisplay = FDE_CSSDISPLAY_None;
+ FX_BOOL bContentNode = FALSE;
+ FX_FLOAT fSpaceBelow = 0;
+ IFDE_CSSComputedStyle *pStyle = NULL;
+ CFX_WideString wsName;
+ if (bEndBreak) {
+ FX_BOOL bCurOl = FALSE;
+ FX_BOOL bCurLi = FALSE;
+ IFDE_XMLElement *pElement = NULL;
+ if (pContext != NULL) {
+ if(m_bBlockContinue || (m_pLoader && pXMLNode == m_pLoader->m_pXMLNode)) {
+ m_bBlockContinue = TRUE;
+ }
+ if(pXMLNode->GetType() == FDE_XMLNODE_Text) {
+ bContentNode = TRUE;
+ } else if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+ pElement = (IFDE_XMLElement *)pXMLNode;
+ pElement->GetLocalTagName(wsName);
+ }
+ if (wsName == FX_WSTRC(L"ol")) {
+ bIsOl = TRUE;
+ bCurOl = TRUE;
+ }
+ if(m_bBlockContinue || bContentNode == FALSE) {
+ eDisplay = pContext->GetDisplay();
+ if (eDisplay != FDE_CSSDISPLAY_Block && eDisplay != FDE_CSSDISPLAY_Inline && eDisplay != FDE_CSSDISPLAY_ListItem) {
+ return TRUE;
+ }
+ pStyle = m_textParser.ComputeStyle(pXMLNode, pParentStyle);
+ InitBreak(bContentNode ? pParentStyle : pStyle, eDisplay, szText.x, pXMLNode, pParentStyle);
+ if ((eDisplay == FDE_CSSDISPLAY_Block || eDisplay == FDE_CSSDISPLAY_ListItem) && (pStyle != NULL)
+ && (wsName.IsEmpty() || (wsName != FX_WSTRC(L"body") && wsName != FX_WSTRC(L"html") && wsName != FX_WSTRC(L"ol") && wsName != FX_WSTRC(L"ul")))) {
+ const FDE_CSSRECT *pRect = pStyle->GetBoundaryStyles()->GetMarginWidth();
+ if (pRect) {
+ fLinePos += pRect->top.GetValue();
+ fSpaceBelow = pRect->bottom.GetValue();
+ }
+ }
+ if (wsName == FX_WSTRC(L"a")) {
+ CFX_WideString wsLinkContent;
+ FXSYS_assert(pElement);
+ pElement->GetString(FX_WSTRC(L"href").GetPtr(), wsLinkContent);
+ if (!wsLinkContent.IsEmpty()) {
+ pLinkData = FDE_NewWith(m_pAllocator)CXFA_LinkUserData(m_pAllocator, wsLinkContent.GetBuffer(wsLinkContent.GetLength()));
+ wsLinkContent.ReleaseBuffer(wsLinkContent.GetLength());
+ }
+ }
+ FX_INT32 iTabCount = m_textParser.CountTabs(bContentNode ? pParentStyle : pStyle);
+ FX_BOOL bSpaceRun = m_textParser.IsSpaceRun(bContentNode ? pParentStyle : pStyle);
+ CFX_WideString wsText;
+ if (bContentNode && iTabCount == 0) {
+ ((IFDE_XMLText *)pXMLNode)->GetText(wsText);
+ } else if (wsName == FX_WSTRC(L"br")) {
+ wsText = L'\n';
+ } else if (wsName == FX_WSTRC(L"li")) {
+ bCurLi = TRUE;
+ if (bIsOl) {
+ wsText.Format(FX_LPCWSTR(L"%d. "), iLiCount);
+ } else {
+ wsText = 0x00B7 + FX_WSTRC(L" ");
+ }
+ } else if (!bContentNode) {
+ if (iTabCount > 0)
+ while (iTabCount-- > 0) {
+ wsText += L'\t';
+ }
+ else {
+ m_textParser.GetEmbbedObj(m_pTextProvider, pXMLNode, wsText);
+ }
+ }
+ FX_INT32 iLength = wsText.GetLength();
+ if (iLength > 0 && bContentNode && !bSpaceRun) {
+ ProcessText(wsText);
+ }
+ if (m_pLoader) {
+ if (wsText.GetLength() > 0 && (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) {
+ wsText.TrimLeft(0x20);
+ }
+ if (FDE_CSSDISPLAY_Block == eDisplay) {
+ m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE;
+ } else if (FDE_CSSDISPLAY_Inline == eDisplay && (m_pLoader->m_dwFlags & XFA_LOADERCNTXTFLG_FILTERSPACE)) {
+ m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE;
+ } else if (wsText.GetLength() > 0 && (0x20 == wsText.GetAt(wsText.GetLength() - 1))) {
+ m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE;
+ } else if (wsText.GetLength() == 0)
+ ;
+ else {
+ m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE;
+ }
+ }
+ if (wsText.GetLength() > 0) {
+ if (m_pLoader == NULL || m_pLoader->m_iChar == 0) {
+ if (pLinkData) {
+ pLinkData->AddRef();
+ }
+ CXFA_TextUserData *pUserData = FDE_NewWith(m_pAllocator)CXFA_TextUserData(m_pAllocator, bContentNode ? pParentStyle : pStyle, pLinkData);
+ m_pBreak->SetUserData(pUserData);
+ }
+ if (AppendChar(wsText, fLinePos, 0, bSavePieces)) {
+ if ( m_pLoader) {
+ m_pLoader->m_dwFlags &= ~XFA_LOADERCNTXTFLG_FILTERSPACE;
+ }
+ if (IsEnd(bSavePieces)) {
+ if (m_pLoader && m_pLoader->m_iTotalLines > -1) {
+ m_pLoader->m_pXMLNode = pXMLNode;
+ m_pLoader->m_pParentStyle = pParentStyle;
+ }
+ if (pStyle != NULL) {
+ pStyle->Release();
+ }
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+ }
+ }
+ FX_BOOL ret = TRUE;
+ for (IFDE_XMLNode *pChildNode = pXMLNode->GetNodeItem(IFDE_XMLNode::FirstChild); pChildNode; pChildNode = pChildNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ if (bCurOl) {
+ iLiCount++;
+ }
+ ret = LoadRichText(pChildNode, szText, fLinePos, pContext ? pStyle : pParentStyle, bSavePieces, pLinkData, TRUE, bIsOl, iLiCount);
+ if(ret == FALSE) {
+ return FALSE;
+ }
+ }
+ if (m_pLoader) {
+ if (FDE_CSSDISPLAY_Block == eDisplay) {
+ m_pLoader->m_dwFlags |= XFA_LOADERCNTXTFLG_FILTERSPACE;
+ }
+ }
+ if (bCurLi) {
+ EndBreak(FX_RTFBREAK_LineBreak, fLinePos, bSavePieces);
+ }
+ } else {
+ if (pContext != NULL) {
+ eDisplay = pContext->GetDisplay();
+ }
+ }
+ if(m_bBlockContinue) {
+ if (pContext != NULL && !bContentNode) {
+ FX_DWORD dwStatus = (eDisplay == FDE_CSSDISPLAY_Block) ? FX_RTFBREAK_ParagraphBreak : FX_RTFBREAK_PieceBreak;
+ EndBreak(dwStatus, fLinePos, bSavePieces);
+ if (eDisplay == FDE_CSSDISPLAY_Block) {
+ fLinePos += fSpaceBelow;
+ if (m_pTabstopContext) {
+ m_pTabstopContext->RemoveAll();
+ }
+ }
+ if ( wsName == FX_WSTRC(L"a")) {
+ if (pLinkData != NULL) {
+ FX_DWORD dwRefCount = pLinkData->Release();
+ pLinkData = NULL;
+ }
+ }
+ if (IsEnd(bSavePieces)) {
+ if (pStyle) {
+ pStyle->Release();
+ }
+ if (m_pLoader && m_pLoader->m_iTotalLines > -1) {
+ m_pLoader->m_pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling);
+ m_pLoader->m_pParentStyle = pParentStyle;
+ }
+ return FALSE;
+ }
+ }
+ }
+ if (pStyle != NULL) {
+ pStyle->Release();
+ }
+ return TRUE;
+}
+FX_BOOL CXFA_TextLayout::AppendChar(const CFX_WideString &wsText, FX_FLOAT &fLinePos, FX_FLOAT fSpaceAbove, FX_BOOL bSavePieces)
+{
+ FX_DWORD dwStatus = 0;
+ FX_INT32 iChar = 0;
+ if (m_pLoader) {
+ iChar = m_pLoader->m_iChar;
+ }
+ FX_INT32 iLength = wsText.GetLength();
+ for (FX_INT32 i = iChar; i < iLength; i++) {
+ FX_WCHAR wch = wsText.GetAt(i);
+ if (wch == 0xA0) {
+ wch = 0x20;
+ }
+ if ((dwStatus = m_pBreak->AppendChar(wch)) > FX_RTFBREAK_PieceBreak) {
+ AppendTextLine(dwStatus, fLinePos, bSavePieces);
+ if (IsEnd(bSavePieces)) {
+ if (m_pLoader != NULL) {
+ m_pLoader->m_iChar = i;
+ }
+ return TRUE;
+ }
+ if (dwStatus == FX_RTFBREAK_ParagraphBreak && m_bRichText) {
+ fLinePos += fSpaceAbove;
+ }
+ }
+ }
+ if(m_pLoader) {
+ m_pLoader->m_iChar = 0;
+ }
+ return FALSE;
+}
+FX_BOOL CXFA_TextLayout::IsEnd(FX_BOOL bSavePieces)
+{
+ if (!bSavePieces) {
+ return FALSE;
+ }
+ if (m_pLoader && m_pLoader->m_iTotalLines > 0) {
+ return m_iLines >= m_pLoader->m_iTotalLines;
+ }
+ return FALSE;
+}
+void CXFA_TextLayout::ProcessText(CFX_WideString &wsText)
+{
+ FX_INT32 iLen = wsText.GetLength();
+ if (iLen == 0) {
+ return;
+ }
+ FX_LPWSTR psz = wsText.GetBuffer(iLen);
+ FX_INT32 iTrimLeft = 0;
+ FX_WCHAR wch = 0, wPrev = 0;
+ for (FX_INT32 i = 0; i < iLen; i++) {
+ wch = psz[i];
+ if (wch < 0x20) {
+ wch = 0x20;
+ }
+ if (wch == 0x20 && wPrev == 0x20) {
+ continue;
+ }
+ wPrev = wch;
+ psz[iTrimLeft++] = wch;
+ }
+ wsText.ReleaseBuffer(iLen);
+ wsText = wsText.Left(iTrimLeft);
+}
+void CXFA_TextLayout::EndBreak(FX_DWORD dwStatus, FX_FLOAT &fLinePos, FX_BOOL bSavePieces)
+{
+ dwStatus = m_pBreak->EndBreak(dwStatus);
+ if (dwStatus > FX_RTFBREAK_PieceBreak) {
+ AppendTextLine(dwStatus, fLinePos, bSavePieces, TRUE);
+ }
+}
+void CXFA_TextLayout::DoTabstops(IFDE_CSSComputedStyle *pStyle, CXFA_PieceLine *pPieceLine)
+{
+ if (m_pTabstopContext == NULL || m_pTabstopContext->m_iTabCount == 0) {
+ return;
+ }
+ if (pStyle == NULL || pPieceLine == NULL) {
+ return;
+ }
+ FX_INT32 iPieces = pPieceLine->m_textPieces.GetSize();
+ if (iPieces == 0) {
+ return;
+ }
+ XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPieces - 1);
+ FX_INT32 &iTabstopsIndex = m_pTabstopContext->m_iTabIndex;
+ FX_INT32 iCount = m_textParser.CountTabs(pStyle);
+ if (iTabstopsIndex > m_pTabstopContext->m_iTabCount - 1) {
+ return;
+ }
+ if (iCount > 0) {
+ iTabstopsIndex++;
+ m_pTabstopContext->m_bTabstops = TRUE;
+ FX_FLOAT fRight = 0;
+ if (iPieces > 1) {
+ XFA_LPTEXTPIECE p = pPieceLine->m_textPieces.GetAt(iPieces - 2);
+ fRight = p->rtPiece.right();
+ }
+ m_pTabstopContext->m_fTabWidth = pPiece->rtPiece.width + pPiece->rtPiece.left - fRight;
+ } else if (iTabstopsIndex > -1) {
+ FX_FLOAT fLeft = 0;
+ if (m_pTabstopContext->m_bTabstops) {
+ XFA_TABSTOPS *pTabstops = m_pTabstopContext->m_tabstops.GetDataPtr(iTabstopsIndex);
+ FX_DWORD dwAlgin = pTabstops->dwAlign;
+ if (dwAlgin == FX_HashCode_String_GetW((FX_LPCWSTR)L"center", 6)) {
+ fLeft = pPiece->rtPiece.width / 2.0f;
+ } else if (dwAlgin == FX_HashCode_String_GetW((FX_LPCWSTR)L"right", 5)
+ || dwAlgin == FX_HashCode_String_GetW((FX_LPCWSTR)L"before", 6)) {
+ fLeft = pPiece->rtPiece.width;
+ } else if (dwAlgin == FX_HashCode_String_GetW((FX_LPCWSTR)L"decimal", 7)) {
+ FX_INT32 iChars = pPiece->iChars;
+ for (FX_INT32 i = 0; i < iChars; i++) {
+ if (pPiece->pszText[i] == L'.') {
+ break;
+ }
+ fLeft += pPiece->pWidths[i] / 20000.0f;
+ }
+ }
+ m_pTabstopContext->m_fLeft = FX_MIN(fLeft, m_pTabstopContext->m_fTabWidth);
+ m_pTabstopContext->m_bTabstops = FALSE;
+ m_pTabstopContext->m_fTabWidth = 0;
+ }
+ pPiece->rtPiece.left -= m_pTabstopContext->m_fLeft;
+ }
+}
+void CXFA_TextLayout::AppendTextLine(FX_DWORD dwStatus, FX_FLOAT &fLinePos, FX_BOOL bSavePieces, FX_BOOL bEndBreak)
+{
+ FX_INT32 iPieces = m_pBreak->CountBreakPieces();
+ if (iPieces < 1) {
+ return;
+ }
+ IFDE_CSSComputedStyle *pStyle = NULL;
+ if (bSavePieces) {
+ CXFA_PieceLine *pPieceLine = FDE_NewWith(m_pAllocator)CXFA_PieceLine;
+ m_pieceLines.Add(pPieceLine);
+ if (m_pTabstopContext) {
+ m_pTabstopContext->Reset();
+ }
+ FX_FLOAT fLineStep = 0, fBaseLine = 0;
+ FX_INT32 i = 0;
+ for (i = 0; i < iPieces; i++) {
+ const CFX_RTFPiece *pPiece = m_pBreak->GetBreakPiece(i);
+ CXFA_TextUserData *pUserData = (CXFA_TextUserData*)pPiece->m_pUserData;
+ if (pUserData != NULL) {
+ pStyle = pUserData->m_pStyle;
+ }
+ FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f;
+ XFA_LPTEXTPIECE pTP = (XFA_LPTEXTPIECE)m_pAllocator->Alloc(sizeof(XFA_TEXTPIECE));
+ pTP->pszText = (FX_LPWSTR)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(FX_WCHAR));
+ pTP->pWidths = (FX_INT32*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(FX_INT32));
+ pTP->iChars = pPiece->m_iChars;
+ pPiece->GetString(pTP->pszText);
+ pPiece->GetWidths(pTP->pWidths);
+ pTP->iBidiLevel = pPiece->m_iBidiLevel;
+ pTP->iHorScale = pPiece->m_iHorizontalScale;
+ pTP->iVerScale = pPiece->m_iVerticalScale;
+ m_textParser.GetUnderline(m_pTextProvider, pStyle, pTP->iUnderline, pTP->iPeriod);
+ m_textParser.GetLinethrough(m_pTextProvider, pStyle, pTP->iLineThrough);
+ pTP->dwColor = m_textParser.GetColor(m_pTextProvider, pStyle);
+ pTP->pFont = m_textParser.GetFont(m_pTextProvider, pStyle);
+ pTP->fFontSize = m_textParser.GetFontSize(m_pTextProvider, pStyle);
+ pTP->rtPiece.left = pPiece->m_iStartPos / 20000.0f;
+ pTP->rtPiece.width = pPiece->m_iWidth / 20000.0f;
+ pTP->rtPiece.height = (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f;
+ FX_FLOAT fBaseLineTemp = m_textParser.GetBaseline(m_pTextProvider, pStyle);
+ pTP->rtPiece.top = fBaseLineTemp;
+ pPieceLine->m_textPieces.Add(pTP);
+ FX_FLOAT fLineHeight = m_textParser.GetLineHeight(m_pTextProvider, pStyle, m_iLines == 0, fVerScale);
+ if (fBaseLineTemp > 0) {
+ FX_FLOAT fLineHeightTmp = fBaseLineTemp + pTP->rtPiece.height;
+ if (fLineHeight < fLineHeightTmp) {
+ fLineHeight = fLineHeightTmp;
+ } else {
+ fBaseLineTemp = 0;
+ }
+ } else if (fBaseLine < -fBaseLineTemp) {
+ fBaseLine = -fBaseLineTemp;
+ }
+ fLineStep = FX_MAX(fLineStep, fLineHeight);
+ if ( pUserData != NULL && pUserData->m_pLinkData != NULL) {
+ pUserData->m_pLinkData->AddRef();
+ pTP->pLinkData = pUserData->m_pLinkData;
+ } else {
+ pTP->pLinkData = NULL;
+ }
+ DoTabstops(pStyle, pPieceLine);
+ }
+ for (i = 0; i < iPieces; i++) {
+ XFA_LPTEXTPIECE pTP = pPieceLine->m_textPieces.GetAt(i);
+ FX_FLOAT &fTop = pTP->rtPiece.top;
+ FX_FLOAT fBaseLineTemp = fTop;
+ fTop = fLinePos + fLineStep - pTP->rtPiece.height - fBaseLineTemp;
+ fTop = FX_MAX(0, fTop);
+ }
+ fLinePos += fLineStep + fBaseLine;
+ } else {
+ FX_FLOAT fLineStep = 0;
+ FX_FLOAT fLineWidth = 0;
+ for (FX_INT32 i = 0; i < iPieces; i++) {
+ const CFX_RTFPiece *pPiece = m_pBreak->GetBreakPiece(i);
+ CXFA_TextUserData *pUserData = (CXFA_TextUserData*)pPiece->m_pUserData;
+ if (pUserData != NULL) {
+ pStyle = pUserData->m_pStyle;
+ }
+ FX_FLOAT fVerScale = pPiece->m_iVerticalScale / 100.0f;
+ FX_FLOAT fBaseLine = m_textParser.GetBaseline(m_pTextProvider, pStyle);
+ FX_FLOAT fLineHeight = m_textParser.GetLineHeight(m_pTextProvider, pStyle, m_iLines == 0, fVerScale);
+ if (fBaseLine > 0) {
+ FX_FLOAT fLineHeightTmp = fBaseLine + (FX_FLOAT)pPiece->m_iFontSize * fVerScale / 20.0f;
+ if (fLineHeight < fLineHeightTmp) {
+ fLineHeight = fLineHeightTmp;
+ }
+ }
+ fLineStep = FX_MAX(fLineStep, fLineHeight);
+ fLineWidth += pPiece->m_iWidth / 20000.0f;
+ }
+ fLinePos += fLineStep;
+ m_fMaxWidth = FX_MAX(m_fMaxWidth, fLineWidth);
+ if (m_pLoader && m_pLoader->m_bSaveLineHeight) {
+ FX_FLOAT fHeight = fLinePos - m_pLoader->m_fLastPos;
+ m_pLoader->m_fLastPos = fLinePos;
+ m_pLoader->m_lineHeights.Add(fHeight);
+ }
+ }
+ m_pBreak->ClearBreakPieces();
+ if (dwStatus == FX_RTFBREAK_ParagraphBreak) {
+ m_pBreak->Reset();
+ if (pStyle == NULL && bEndBreak) {
+ CXFA_Para para = m_pTextProvider->GetParaNode();
+ if (para.IsExistInXML()) {
+ FX_FLOAT fStartPos = para.GetMarginLeft();
+ FX_FLOAT fIndent = para.GetTextIndent();
+ if (fIndent > 0) {
+ fStartPos += fIndent;
+ }
+ FX_FLOAT fSpaceBelow = para.GetSpaceBelow();
+ if (fSpaceBelow < 0.1f) {
+ fSpaceBelow = 0;
+ }
+ m_pBreak->SetLinePos(fStartPos);
+ fLinePos += fSpaceBelow;
+ }
+ }
+ }
+ if (pStyle != NULL) {
+ FX_FLOAT fStart = 0;
+ const FDE_CSSRECT *pRect = pStyle->GetBoundaryStyles()->GetMarginWidth();
+ if (pRect) {
+ fStart = pRect->left.GetValue();
+ }
+ FX_FLOAT fTextIndent = pStyle->GetParagraphStyles()->GetTextIndent().GetValue();
+ if (fTextIndent < 0) {
+ fStart -= fTextIndent;
+ }
+ m_pBreak->SetLinePos(fStart);
+ }
+ m_iLines++;
+}
+void CXFA_TextLayout::RenderString(IFDE_RenderDevice *pDevice, IFDE_SolidBrush *pBrush, CXFA_PieceLine *pPieceLine, FX_INT32 iPiece, FXTEXT_CHARPOS *pCharPos, const CFX_Matrix &tmDoc2Device)
+{
+ XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
+ FX_INT32 iCount = GetDisplayPos(pPiece, pCharPos);
+ if (iCount > 0) {
+ pBrush->SetColor(pPiece->dwColor);
+ pDevice->DrawString(pBrush, pPiece->pFont, pCharPos, iCount, pPiece->fFontSize, &tmDoc2Device);
+ }
+ pPieceLine->m_charCounts.Add(iCount);
+}
+void CXFA_TextLayout::RenderPath(IFDE_RenderDevice *pDevice, IFDE_Pen *pPen, CXFA_PieceLine *pPieceLine, FX_INT32 iPiece, FXTEXT_CHARPOS *pCharPos, const CFX_Matrix &tmDoc2Device)
+{
+ XFA_TEXTPIECE *pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
+ FX_BOOL bNoUnderline = pPiece->iUnderline < 1 || pPiece->iUnderline > 2;
+ FX_BOOL bNoLineThrough = pPiece->iLineThrough < 1 || pPiece->iLineThrough > 2;
+ if (bNoUnderline && bNoLineThrough) {
+ return;
+ }
+ pPen->SetColor(pPiece->dwColor);
+ IFDE_Path *pPath = IFDE_Path::Create();
+ FX_INT32 iChars = GetDisplayPos(pPiece, pCharPos);
+ if (iChars > 0) {
+ CFX_PointF pt1, pt2;
+ FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f;
+ FX_INT32 i = 0;
+ if (pPiece->iPeriod == XFA_ATTRIBUTEENUM_Word) {
+ for (FX_INT32 i = 0; i < pPiece->iUnderline; i++) {
+ for (FX_INT32 j = 0; j < iChars; j++) {
+ pt1.x = pCharPos[j].m_OriginX;
+ pt2.x = pt1.x + pCharPos[j].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+ pt1.y = pt2.y = fEndY;
+ pPath->AddLine(pt1, pt2);
+ }
+ fEndY += 2.0f;
+ }
+ } else {
+ pt1.x = pCharPos[0].m_OriginX;
+ pt2.x = pCharPos[iChars - 1].m_OriginX + pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+ for (FX_INT32 i = 0; i < pPiece->iUnderline; i++) {
+ pt1.y = pt2.y = fEndY;
+ pPath->AddLine(pt1, pt2);
+ fEndY += 2.0f;
+ }
+ }
+ fEndY = pCharPos[0].m_OriginY - pPiece->rtPiece.height * 0.25f;
+ pt1.x = pCharPos[0].m_OriginX;
+ pt2.x = pCharPos[iChars - 1].m_OriginX + pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+ for (i = 0; i < pPiece->iLineThrough; i++) {
+ pt1.y = pt2.y = fEndY;
+ pPath->AddLine(pt1, pt2);
+ fEndY += 2.0f;
+ }
+ } else {
+ if (bNoLineThrough && (bNoUnderline || pPiece->iPeriod != XFA_ATTRIBUTEENUM_All)) {
+ goto XFA_RenderPathRet;
+ }
+ FX_INT32 iCharsTmp = 0;
+ FX_INT32 iPiecePrev = iPiece, iPieceNext = iPiece;
+ while (iPiecePrev > 0) {
+ iPiecePrev--;
+ iCharsTmp = pPieceLine->m_charCounts.GetAt(iPiecePrev);
+ if (iCharsTmp > 0) {
+ break;
+ }
+ }
+ if (iCharsTmp == 0) {
+ goto XFA_RenderPathRet;
+ }
+ iCharsTmp = 0;
+ FX_INT32 iPieces = pPieceLine->m_textPieces.GetSize();
+ while (iPieceNext < iPieces - 1) {
+ iPieceNext++;
+ iCharsTmp = pPieceLine->m_charCounts.GetAt(iPieceNext);
+ if (iCharsTmp > 0) {
+ break;
+ }
+ }
+ if (iCharsTmp == 0) {
+ goto XFA_RenderPathRet;
+ }
+ FX_FLOAT fOrgX = 0.0f, fEndX = 0.0f;
+ pPiece = pPieceLine->m_textPieces.GetAt(iPiecePrev);
+ iChars = GetDisplayPos(pPiece, pCharPos);
+ if (iChars < 1) {
+ goto XFA_RenderPathRet;
+ }
+ fOrgX = pCharPos[iChars - 1].m_OriginX + pCharPos[iChars - 1].m_FontCharWidth * pPiece->fFontSize / 1000.0f;
+ pPiece = pPieceLine->m_textPieces.GetAt(iPieceNext);
+ iChars = GetDisplayPos(pPiece, pCharPos);
+ if (iChars < 1) {
+ goto XFA_RenderPathRet;
+ }
+ fEndX = pCharPos[0].m_OriginX;
+ CFX_PointF pt1, pt2;
+ pt1.x = fOrgX, pt2.x = fEndX;
+ FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f;
+ FX_INT32 i = 0;
+ for (i = 0; i < pPiece->iUnderline; i++) {
+ pt1.y = pt2.y = fEndY;
+ pPath->AddLine(pt1, pt2);
+ fEndY += 2.0f;
+ }
+ fEndY = pCharPos[0].m_OriginY - pPiece->rtPiece.height * 0.25f;
+ for (i = 0; i < pPiece->iLineThrough; i++) {
+ pt1.y = pt2.y = fEndY;
+ pPath->AddLine(pt1, pt2);
+ fEndY += 2.0f;
+ }
+ }
+ pDevice->DrawPath(pPen, 1, pPath, &tmDoc2Device);
+XFA_RenderPathRet:
+ pPath->Release();
+}
+FX_INT32 CXFA_TextLayout::GetDisplayPos(XFA_LPCTEXTPIECE pPiece, FXTEXT_CHARPOS *pCharPos, FX_BOOL bCharCode )
+{
+ if (pPiece == NULL) {
+ return 0;
+ }
+ FX_RTFTEXTOBJ tr;
+ if (!ToRun(pPiece, tr)) {
+ return 0;
+ }
+ return m_pBreak->GetDisplayPos(&tr, pCharPos, bCharCode);
+}
+FX_BOOL CXFA_TextLayout::ToRun(XFA_LPCTEXTPIECE pPiece, FX_RTFTEXTOBJ &tr)
+{
+ FX_INT32 iLength = pPiece->iChars;
+ if (iLength < 1) {
+ return FALSE;
+ }
+ tr.pStr = pPiece->pszText;
+ tr.pFont = pPiece->pFont;
+ tr.pRect = &pPiece->rtPiece;
+ tr.pWidths = pPiece->pWidths;
+ tr.iLength = iLength;
+ tr.fFontSize = pPiece->fFontSize;
+ tr.iBidiLevel = pPiece->iBidiLevel;
+ tr.iCharRotation = 0;
+ tr.wLineBreakChar = L'\n';
+ tr.iVerticalScale = pPiece->iVerScale;
+ tr.dwLayoutStyles = FX_RTFLAYOUTSTYLE_ExpandTab;
+ tr.iHorizontalScale = pPiece->iHorScale;
+ return TRUE;
+}
|