| Index: xfa/src/fxfa/src/app/xfa_textlayout.cpp
|
| diff --git a/xfa/src/fxfa/src/app/xfa_textlayout.cpp b/xfa/src/fxfa/src/app/xfa_textlayout.cpp
|
| index 4eddabc0bdc8a569cef799764dd7fdc628f71d3b..b949734fe98f9ec1a31a73fda185e95612d788d3 100644
|
| --- a/xfa/src/fxfa/src/app/xfa_textlayout.cpp
|
| +++ b/xfa/src/fxfa/src/app/xfa_textlayout.cpp
|
| @@ -1,2022 +1,2022 @@
|
| -// 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 <algorithm>
|
| -
|
| -#include "xfa/src/foxitlib.h"
|
| -#include "xfa/src/fxfa/src/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 = new CFX_WideString();
|
| - CFX_WideString* pValue = new CFX_WideString();
|
| - *pName = wsAttr;
|
| - *pValue = wsValue;
|
| - m_Attributes.SetAt(pName, pValue);
|
| -}
|
| -void CXFA_TextParseContext::SetDecls(const IFDE_CSSDeclaration** ppDeclArray,
|
| - int32_t iDeclCount) {
|
| - if (iDeclCount <= 0 || ppDeclArray == NULL) {
|
| - return;
|
| - }
|
| - m_dwMatchedDecls = iDeclCount;
|
| - m_ppMatchedDecls = FX_Alloc(IFDE_CSSDeclaration*, iDeclCount);
|
| - FX_memcpy(m_ppMatchedDecls, ppDeclArray,
|
| - iDeclCount * sizeof(IFDE_CSSDeclaration*));
|
| -}
|
| -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_WCHAR s_pStyle[] =
|
| - 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;"
|
| - L"margin-bottom:0}ul,ol{margin:1.12em 0}"
|
| - L"a{color:#0000ff;text-decoration:underline}b{font-weight:bolder}i{font-"
|
| - L"style:italic}"
|
| - L"sup{vertical-align:+15em;font-size:.66em}sub{vertical-align:-15em;font-"
|
| - L"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 = static_cast<CXFA_TextParseContext*>(
|
| - m_mapXMLNodeToParseContext.GetValueAt(pXMLNode));
|
| - if (!pContext)
|
| - return nullptr;
|
| - pContext->m_pParentStyle = pParentStyle;
|
| - pParentStyle->AddRef();
|
| - CXFA_CSSTagProvider tagProvider;
|
| - ParseTagInfo(pXMLNode, tagProvider);
|
| - if (tagProvider.m_bContent)
|
| - return nullptr;
|
| - 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;
|
| - int32_t 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 int32_t 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;
|
| - }
|
| -}
|
| -int32_t CXFA_TextParser::GetVAlgin(IXFA_TextProvider* pTextProvider) const {
|
| - int32_t 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;
|
| -}
|
| -int32_t 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();
|
| - int32_t 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(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;
|
| -}
|
| -int32_t CXFA_TextParser::GetHorScale(IXFA_TextProvider* pTextProvider,
|
| - IFDE_CSSComputedStyle* pStyle,
|
| - IFDE_XMLNode* pXMLNode) const {
|
| - if (pStyle) {
|
| - CFX_WideString wsValue;
|
| - if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-horizontal-scale"),
|
| - wsValue)) {
|
| - return wsValue.GetInteger();
|
| - }
|
| - while (pXMLNode) {
|
| - CXFA_TextParseContext* pContext = static_cast<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 static_cast<int32_t>(font.GetHorizontalScale());
|
| - }
|
| - return 100;
|
| -}
|
| -int32_t 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 (int32_t)font.GetVerticalScale();
|
| - }
|
| - return 100;
|
| -}
|
| -void CXFA_TextParser::GetUnderline(IXFA_TextProvider* pTextProvider,
|
| - IFDE_CSSComputedStyle* pStyle,
|
| - int32_t& iUnderline,
|
| - int32_t& 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,
|
| - int32_t& 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 = std::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) == 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;
|
| - }
|
| - int32_t iLength = wsValue.GetLength();
|
| - const FX_WCHAR* pTabStops = wsValue;
|
| - int32_t iCur = 0;
|
| - int32_t 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 {
|
| - int32_t 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_bHasBlock(FALSE),
|
| - m_pTextProvider(pTextProvider),
|
| - m_pTextDataNode(nullptr),
|
| - m_bRichText(FALSE),
|
| - m_pAllocator(nullptr),
|
| - m_pBreak(nullptr),
|
| - m_pLoader(nullptr),
|
| - m_iLines(0),
|
| - m_fMaxWidth(0),
|
| - m_pTabstopContext(nullptr),
|
| - m_bBlockContinue(TRUE) {
|
| - FXSYS_assert(m_pTextProvider);
|
| -}
|
| -CXFA_TextLayout::~CXFA_TextLayout() {
|
| - m_textParser.Reset();
|
| - delete m_pLoader;
|
| - delete m_pTabstopContext;
|
| - Unload();
|
| -}
|
| -void CXFA_TextLayout::Unload() {
|
| - int32_t iCount = m_pieceLines.GetSize();
|
| - for (int32_t 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()) {
|
| - int32_t 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->SetLineBoundary(fStart, fLineWidth);
|
| - m_pBreak->SetLineStartPos(fStartPos);
|
| - if (font.IsExistInXML()) {
|
| - m_pBreak->SetHorizontalScale((int32_t)font.GetHorizontalScale());
|
| - m_pBreak->SetVerticalScale((int32_t)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) {
|
| - int32_t 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->SetLineBoundary(fStart, fLineWidth);
|
| - FX_FLOAT fIndent = pParaStyle->GetTextIndent().GetValue();
|
| - if (fIndent > 0) {
|
| - fStart += fIndent;
|
| - }
|
| - m_pBreak->SetLineStartPos(fStart);
|
| - m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle));
|
| - if (m_pTabstopContext == NULL) {
|
| - m_pTabstopContext = new CXFA_TextTabstopsContext;
|
| - }
|
| - m_textParser.GetTabstops(pStyle, m_pTabstopContext);
|
| - for (int32_t 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());
|
| -}
|
| -int32_t 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;
|
| - }
|
| - int32_t 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 (int32_t 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 = 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(int32_t iBlockIndex,
|
| - FX_FLOAT& fCalcHeight,
|
| - FX_FLOAT fContentAreaHeight,
|
| - FX_FLOAT fTextHeight) {
|
| - if (m_pLoader == NULL) {
|
| - return FALSE;
|
| - }
|
| - int32_t 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) {
|
| - int32_t 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;
|
| - int32_t 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 (int32_t i = 0; i < iBlockIndex; i++) {
|
| - fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
|
| - }
|
| - }
|
| - }
|
| - int32_t iCount = m_pLoader->m_lineHeights.GetSize();
|
| - int32_t 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;
|
| -}
|
| -int32_t CXFA_TextLayout::CountBlocks() const {
|
| - int32_t 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(int32_t 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);
|
| - int32_t iCount = m_Blocks.GetSize();
|
| - int32_t 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 (int32_t 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, int32_t iBlockIndex) {
|
| - if (!m_pLoader) {
|
| - return;
|
| - }
|
| - int32_t iCountHeight = m_pLoader->m_lineHeights.GetSize();
|
| - if (iCountHeight == 0) {
|
| - return;
|
| - }
|
| - FX_BOOL bEndItem = TRUE;
|
| - int32_t iBlockCount = m_Blocks.GetSize();
|
| - FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset;
|
| - int32_t iLineIndex = 0;
|
| - if (iBlockIndex > 0) {
|
| - int32_t iBlockHeightCount = m_pLoader->m_BlocksHeight.GetSize();
|
| - iBlockHeightCount /= 2;
|
| - if (iBlockHeightCount >= iBlockIndex) {
|
| - for (int32_t 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);
|
| - }
|
| - int32_t 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,
|
| - int32_t 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) {
|
| - int32_t iBlockCount = CountBlocks();
|
| - for (int32_t i = 0; i < iBlockCount; i++) {
|
| - Layout(i);
|
| - }
|
| - }
|
| - FXTEXT_CHARPOS* pCharPos = NULL;
|
| - int32_t iCharCount = 0;
|
| - int32_t iLineStart = 0;
|
| - int32_t iPieceLines = m_pieceLines.GetSize();
|
| - int32_t 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 (int32_t i = 0; i < iPieceLines; i++) {
|
| - if (i + iLineStart >= m_pieceLines.GetSize()) {
|
| - break;
|
| - }
|
| - CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i + iLineStart);
|
| - int32_t iPieces = pPieceLine->m_textPieces.GetSize();
|
| - int32_t j = 0;
|
| - for (j = 0; j < iPieces; j++) {
|
| - XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
|
| - int32_t iChars = pPiece->iChars;
|
| - if (iCharCount < iChars) {
|
| - FX_Free(pCharPos);
|
| - pCharPos = FX_Alloc(FXTEXT_CHARPOS, iChars);
|
| - 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);
|
| - FX_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;
|
| - }
|
| - int32_t iCount = m_pieceLines.GetSize();
|
| - for (int32_t i = 0; i < iCount; i++) {
|
| - CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i);
|
| - int32_t iPieces = pPieceLine->m_textPieces.GetSize();
|
| - for (int32_t 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;
|
| - }
|
| - int32_t 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,
|
| - int32_t 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());
|
| - }
|
| - }
|
| - int32_t 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(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);
|
| - }
|
| - }
|
| - int32_t 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) {
|
| - pLinkData->Release();
|
| - pLinkData = nullptr;
|
| - }
|
| - }
|
| - 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;
|
| - int32_t iChar = 0;
|
| - if (m_pLoader) {
|
| - iChar = m_pLoader->m_iChar;
|
| - }
|
| - int32_t iLength = wsText.GetLength();
|
| - for (int32_t 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) {
|
| - int32_t iLen = wsText.GetLength();
|
| - if (iLen == 0) {
|
| - return;
|
| - }
|
| - FX_WCHAR* psz = wsText.GetBuffer(iLen);
|
| - int32_t iTrimLeft = 0;
|
| - FX_WCHAR wch = 0, wPrev = 0;
|
| - for (int32_t 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;
|
| - }
|
| - int32_t iPieces = pPieceLine->m_textPieces.GetSize();
|
| - if (iPieces == 0) {
|
| - return;
|
| - }
|
| - XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPieces - 1);
|
| - int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex;
|
| - int32_t 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(L"center", 6)) {
|
| - fLeft = pPiece->rtPiece.width / 2.0f;
|
| - } else if (dwAlgin == FX_HashCode_String_GetW(L"right", 5) ||
|
| - dwAlgin == FX_HashCode_String_GetW(L"before", 6)) {
|
| - fLeft = pPiece->rtPiece.width;
|
| - } else if (dwAlgin == FX_HashCode_String_GetW(L"decimal", 7)) {
|
| - int32_t iChars = pPiece->iChars;
|
| - for (int32_t i = 0; i < iChars; i++) {
|
| - if (pPiece->pszText[i] == L'.') {
|
| - break;
|
| - }
|
| - fLeft += pPiece->pWidths[i] / 20000.0f;
|
| - }
|
| - }
|
| - m_pTabstopContext->m_fLeft =
|
| - std::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) {
|
| - int32_t 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;
|
| - int32_t 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_WCHAR*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(FX_WCHAR));
|
| - pTP->pWidths =
|
| - (int32_t*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(int32_t));
|
| - 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 = std::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 = std::max(0.0f, fTop);
|
| - }
|
| - fLinePos += fLineStep + fBaseLine;
|
| - } else {
|
| - FX_FLOAT fLineStep = 0;
|
| - FX_FLOAT fLineWidth = 0;
|
| - for (int32_t 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 = std::max(fLineStep, fLineHeight);
|
| - fLineWidth += pPiece->m_iWidth / 20000.0f;
|
| - }
|
| - fLinePos += fLineStep;
|
| - m_fMaxWidth = std::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);
|
| - }
|
| - }
|
| - if (pStyle) {
|
| - pStyle->AddRef();
|
| - }
|
| - m_pBreak->ClearBreakPieces();
|
| - if (dwStatus == FX_RTFBREAK_ParagraphBreak) {
|
| - m_pBreak->Reset();
|
| - if (!pStyle && 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->SetLineStartPos(fStartPos);
|
| - fLinePos += fSpaceBelow;
|
| - }
|
| - }
|
| - }
|
| - if (pStyle) {
|
| - 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->SetLineStartPos(fStart);
|
| - pStyle->Release();
|
| - }
|
| - m_iLines++;
|
| -}
|
| -void CXFA_TextLayout::RenderString(IFDE_RenderDevice* pDevice,
|
| - IFDE_SolidBrush* pBrush,
|
| - CXFA_PieceLine* pPieceLine,
|
| - int32_t iPiece,
|
| - FXTEXT_CHARPOS* pCharPos,
|
| - const CFX_Matrix& tmDoc2Device) {
|
| - XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
|
| - int32_t 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,
|
| - int32_t 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();
|
| - int32_t iChars = GetDisplayPos(pPiece, pCharPos);
|
| - if (iChars > 0) {
|
| - CFX_PointF pt1, pt2;
|
| - FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f;
|
| - int32_t i = 0;
|
| - if (pPiece->iPeriod == XFA_ATTRIBUTEENUM_Word) {
|
| - for (int32_t i = 0; i < pPiece->iUnderline; i++) {
|
| - for (int32_t 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 (int32_t 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;
|
| - }
|
| - int32_t iCharsTmp = 0;
|
| - int32_t 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;
|
| - int32_t 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;
|
| - int32_t 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();
|
| -}
|
| -int32_t 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) {
|
| - int32_t 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;
|
| -}
|
| +// 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 <algorithm>
|
| +
|
| +#include "xfa/src/foxitlib.h"
|
| +#include "xfa/src/fxfa/src/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 = new CFX_WideString();
|
| + CFX_WideString* pValue = new CFX_WideString();
|
| + *pName = wsAttr;
|
| + *pValue = wsValue;
|
| + m_Attributes.SetAt(pName, pValue);
|
| +}
|
| +void CXFA_TextParseContext::SetDecls(const IFDE_CSSDeclaration** ppDeclArray,
|
| + int32_t iDeclCount) {
|
| + if (iDeclCount <= 0 || ppDeclArray == NULL) {
|
| + return;
|
| + }
|
| + m_dwMatchedDecls = iDeclCount;
|
| + m_ppMatchedDecls = FX_Alloc(IFDE_CSSDeclaration*, iDeclCount);
|
| + FX_memcpy(m_ppMatchedDecls, ppDeclArray,
|
| + iDeclCount * sizeof(IFDE_CSSDeclaration*));
|
| +}
|
| +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_WCHAR s_pStyle[] =
|
| + 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;"
|
| + L"margin-bottom:0}ul,ol{margin:1.12em 0}"
|
| + L"a{color:#0000ff;text-decoration:underline}b{font-weight:bolder}i{font-"
|
| + L"style:italic}"
|
| + L"sup{vertical-align:+15em;font-size:.66em}sub{vertical-align:-15em;font-"
|
| + L"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 = static_cast<CXFA_TextParseContext*>(
|
| + m_mapXMLNodeToParseContext.GetValueAt(pXMLNode));
|
| + if (!pContext)
|
| + return nullptr;
|
| + pContext->m_pParentStyle = pParentStyle;
|
| + pParentStyle->AddRef();
|
| + CXFA_CSSTagProvider tagProvider;
|
| + ParseTagInfo(pXMLNode, tagProvider);
|
| + if (tagProvider.m_bContent)
|
| + return nullptr;
|
| + 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;
|
| + int32_t 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 int32_t 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;
|
| + }
|
| +}
|
| +int32_t CXFA_TextParser::GetVAlgin(IXFA_TextProvider* pTextProvider) const {
|
| + int32_t 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;
|
| +}
|
| +int32_t 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();
|
| + int32_t 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(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;
|
| +}
|
| +int32_t CXFA_TextParser::GetHorScale(IXFA_TextProvider* pTextProvider,
|
| + IFDE_CSSComputedStyle* pStyle,
|
| + IFDE_XMLNode* pXMLNode) const {
|
| + if (pStyle) {
|
| + CFX_WideString wsValue;
|
| + if (pStyle->GetCustomStyle(FX_WSTRC(L"xfa-font-horizontal-scale"),
|
| + wsValue)) {
|
| + return wsValue.GetInteger();
|
| + }
|
| + while (pXMLNode) {
|
| + CXFA_TextParseContext* pContext = static_cast<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 static_cast<int32_t>(font.GetHorizontalScale());
|
| + }
|
| + return 100;
|
| +}
|
| +int32_t 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 (int32_t)font.GetVerticalScale();
|
| + }
|
| + return 100;
|
| +}
|
| +void CXFA_TextParser::GetUnderline(IXFA_TextProvider* pTextProvider,
|
| + IFDE_CSSComputedStyle* pStyle,
|
| + int32_t& iUnderline,
|
| + int32_t& 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,
|
| + int32_t& 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 = std::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) == 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;
|
| + }
|
| + int32_t iLength = wsValue.GetLength();
|
| + const FX_WCHAR* pTabStops = wsValue;
|
| + int32_t iCur = 0;
|
| + int32_t 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 {
|
| + int32_t 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_bHasBlock(FALSE),
|
| + m_pTextProvider(pTextProvider),
|
| + m_pTextDataNode(nullptr),
|
| + m_bRichText(FALSE),
|
| + m_pAllocator(nullptr),
|
| + m_pBreak(nullptr),
|
| + m_pLoader(nullptr),
|
| + m_iLines(0),
|
| + m_fMaxWidth(0),
|
| + m_pTabstopContext(nullptr),
|
| + m_bBlockContinue(TRUE) {
|
| + FXSYS_assert(m_pTextProvider);
|
| +}
|
| +CXFA_TextLayout::~CXFA_TextLayout() {
|
| + m_textParser.Reset();
|
| + delete m_pLoader;
|
| + delete m_pTabstopContext;
|
| + Unload();
|
| +}
|
| +void CXFA_TextLayout::Unload() {
|
| + int32_t iCount = m_pieceLines.GetSize();
|
| + for (int32_t 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()) {
|
| + int32_t 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->SetLineBoundary(fStart, fLineWidth);
|
| + m_pBreak->SetLineStartPos(fStartPos);
|
| + if (font.IsExistInXML()) {
|
| + m_pBreak->SetHorizontalScale((int32_t)font.GetHorizontalScale());
|
| + m_pBreak->SetVerticalScale((int32_t)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) {
|
| + int32_t 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->SetLineBoundary(fStart, fLineWidth);
|
| + FX_FLOAT fIndent = pParaStyle->GetTextIndent().GetValue();
|
| + if (fIndent > 0) {
|
| + fStart += fIndent;
|
| + }
|
| + m_pBreak->SetLineStartPos(fStart);
|
| + m_pBreak->SetTabWidth(m_textParser.GetTabInterval(pStyle));
|
| + if (m_pTabstopContext == NULL) {
|
| + m_pTabstopContext = new CXFA_TextTabstopsContext;
|
| + }
|
| + m_textParser.GetTabstops(pStyle, m_pTabstopContext);
|
| + for (int32_t 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());
|
| +}
|
| +int32_t 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;
|
| + }
|
| + int32_t 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 (int32_t 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 = 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(int32_t iBlockIndex,
|
| + FX_FLOAT& fCalcHeight,
|
| + FX_FLOAT fContentAreaHeight,
|
| + FX_FLOAT fTextHeight) {
|
| + if (m_pLoader == NULL) {
|
| + return FALSE;
|
| + }
|
| + int32_t 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) {
|
| + int32_t 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;
|
| + int32_t 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 (int32_t i = 0; i < iBlockIndex; i++) {
|
| + fLinePos -= m_pLoader->m_BlocksHeight.ElementAt(i * 2 + 1);
|
| + }
|
| + }
|
| + }
|
| + int32_t iCount = m_pLoader->m_lineHeights.GetSize();
|
| + int32_t 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;
|
| +}
|
| +int32_t CXFA_TextLayout::CountBlocks() const {
|
| + int32_t 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(int32_t 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);
|
| + int32_t iCount = m_Blocks.GetSize();
|
| + int32_t 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 (int32_t 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, int32_t iBlockIndex) {
|
| + if (!m_pLoader) {
|
| + return;
|
| + }
|
| + int32_t iCountHeight = m_pLoader->m_lineHeights.GetSize();
|
| + if (iCountHeight == 0) {
|
| + return;
|
| + }
|
| + FX_BOOL bEndItem = TRUE;
|
| + int32_t iBlockCount = m_Blocks.GetSize();
|
| + FX_FLOAT fLinePos = m_pLoader->m_fStartLineOffset;
|
| + int32_t iLineIndex = 0;
|
| + if (iBlockIndex > 0) {
|
| + int32_t iBlockHeightCount = m_pLoader->m_BlocksHeight.GetSize();
|
| + iBlockHeightCount /= 2;
|
| + if (iBlockHeightCount >= iBlockIndex) {
|
| + for (int32_t 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);
|
| + }
|
| + int32_t 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,
|
| + int32_t 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) {
|
| + int32_t iBlockCount = CountBlocks();
|
| + for (int32_t i = 0; i < iBlockCount; i++) {
|
| + Layout(i);
|
| + }
|
| + }
|
| + FXTEXT_CHARPOS* pCharPos = NULL;
|
| + int32_t iCharCount = 0;
|
| + int32_t iLineStart = 0;
|
| + int32_t iPieceLines = m_pieceLines.GetSize();
|
| + int32_t 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 (int32_t i = 0; i < iPieceLines; i++) {
|
| + if (i + iLineStart >= m_pieceLines.GetSize()) {
|
| + break;
|
| + }
|
| + CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i + iLineStart);
|
| + int32_t iPieces = pPieceLine->m_textPieces.GetSize();
|
| + int32_t j = 0;
|
| + for (j = 0; j < iPieces; j++) {
|
| + XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(j);
|
| + int32_t iChars = pPiece->iChars;
|
| + if (iCharCount < iChars) {
|
| + FX_Free(pCharPos);
|
| + pCharPos = FX_Alloc(FXTEXT_CHARPOS, iChars);
|
| + 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);
|
| + FX_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;
|
| + }
|
| + int32_t iCount = m_pieceLines.GetSize();
|
| + for (int32_t i = 0; i < iCount; i++) {
|
| + CXFA_PieceLine* pPieceLine = m_pieceLines.GetAt(i);
|
| + int32_t iPieces = pPieceLine->m_textPieces.GetSize();
|
| + for (int32_t 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;
|
| + }
|
| + int32_t 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,
|
| + int32_t 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());
|
| + }
|
| + }
|
| + int32_t 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(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);
|
| + }
|
| + }
|
| + int32_t 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) {
|
| + pLinkData->Release();
|
| + pLinkData = nullptr;
|
| + }
|
| + }
|
| + 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;
|
| + int32_t iChar = 0;
|
| + if (m_pLoader) {
|
| + iChar = m_pLoader->m_iChar;
|
| + }
|
| + int32_t iLength = wsText.GetLength();
|
| + for (int32_t 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) {
|
| + int32_t iLen = wsText.GetLength();
|
| + if (iLen == 0) {
|
| + return;
|
| + }
|
| + FX_WCHAR* psz = wsText.GetBuffer(iLen);
|
| + int32_t iTrimLeft = 0;
|
| + FX_WCHAR wch = 0, wPrev = 0;
|
| + for (int32_t 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;
|
| + }
|
| + int32_t iPieces = pPieceLine->m_textPieces.GetSize();
|
| + if (iPieces == 0) {
|
| + return;
|
| + }
|
| + XFA_LPTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPieces - 1);
|
| + int32_t& iTabstopsIndex = m_pTabstopContext->m_iTabIndex;
|
| + int32_t 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(L"center", 6)) {
|
| + fLeft = pPiece->rtPiece.width / 2.0f;
|
| + } else if (dwAlgin == FX_HashCode_String_GetW(L"right", 5) ||
|
| + dwAlgin == FX_HashCode_String_GetW(L"before", 6)) {
|
| + fLeft = pPiece->rtPiece.width;
|
| + } else if (dwAlgin == FX_HashCode_String_GetW(L"decimal", 7)) {
|
| + int32_t iChars = pPiece->iChars;
|
| + for (int32_t i = 0; i < iChars; i++) {
|
| + if (pPiece->pszText[i] == L'.') {
|
| + break;
|
| + }
|
| + fLeft += pPiece->pWidths[i] / 20000.0f;
|
| + }
|
| + }
|
| + m_pTabstopContext->m_fLeft =
|
| + std::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) {
|
| + int32_t 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;
|
| + int32_t 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_WCHAR*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(FX_WCHAR));
|
| + pTP->pWidths =
|
| + (int32_t*)m_pAllocator->Alloc(pPiece->m_iChars * sizeof(int32_t));
|
| + 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 = std::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 = std::max(0.0f, fTop);
|
| + }
|
| + fLinePos += fLineStep + fBaseLine;
|
| + } else {
|
| + FX_FLOAT fLineStep = 0;
|
| + FX_FLOAT fLineWidth = 0;
|
| + for (int32_t 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 = std::max(fLineStep, fLineHeight);
|
| + fLineWidth += pPiece->m_iWidth / 20000.0f;
|
| + }
|
| + fLinePos += fLineStep;
|
| + m_fMaxWidth = std::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);
|
| + }
|
| + }
|
| + if (pStyle) {
|
| + pStyle->AddRef();
|
| + }
|
| + m_pBreak->ClearBreakPieces();
|
| + if (dwStatus == FX_RTFBREAK_ParagraphBreak) {
|
| + m_pBreak->Reset();
|
| + if (!pStyle && 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->SetLineStartPos(fStartPos);
|
| + fLinePos += fSpaceBelow;
|
| + }
|
| + }
|
| + }
|
| + if (pStyle) {
|
| + 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->SetLineStartPos(fStart);
|
| + pStyle->Release();
|
| + }
|
| + m_iLines++;
|
| +}
|
| +void CXFA_TextLayout::RenderString(IFDE_RenderDevice* pDevice,
|
| + IFDE_SolidBrush* pBrush,
|
| + CXFA_PieceLine* pPieceLine,
|
| + int32_t iPiece,
|
| + FXTEXT_CHARPOS* pCharPos,
|
| + const CFX_Matrix& tmDoc2Device) {
|
| + XFA_LPCTEXTPIECE pPiece = pPieceLine->m_textPieces.GetAt(iPiece);
|
| + int32_t 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,
|
| + int32_t 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();
|
| + int32_t iChars = GetDisplayPos(pPiece, pCharPos);
|
| + if (iChars > 0) {
|
| + CFX_PointF pt1, pt2;
|
| + FX_FLOAT fEndY = pCharPos[0].m_OriginY + 1.05f;
|
| + int32_t i = 0;
|
| + if (pPiece->iPeriod == XFA_ATTRIBUTEENUM_Word) {
|
| + for (int32_t i = 0; i < pPiece->iUnderline; i++) {
|
| + for (int32_t 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 (int32_t 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;
|
| + }
|
| + int32_t iCharsTmp = 0;
|
| + int32_t 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;
|
| + int32_t 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;
|
| + int32_t 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();
|
| +}
|
| +int32_t 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) {
|
| + int32_t 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;
|
| +}
|
|
|