Migrated most of the html conversion to the new architecture

This commit is contained in:
Kirill Polyakov
2026-01-26 19:03:34 +03:00
parent 14bb45d2fe
commit a9dc790f92
10 changed files with 1169 additions and 605 deletions

View File

@ -521,6 +521,10 @@ namespace NSCSS
{L"font-size", L"20pt"},
{L"margin-top", L"0"},
{L"margin-bottom", L"0"}});
m_mDefaultStyleData[L"blockquote"] = new CElement(L"blockquote", {{L"margin", L"0px"}});
m_mDefaultStyleData[L"ul"] = new CElement(L"ul", {{L"margin-top", L"100tw"},
{L"margin-bottom", L"100tw"}});
m_mDefaultStyleData[L"textarea"] = new CElement(L"textarea", {{L"border", L"1px solid black"}});
}
CCssCalculator_Private::CCssCalculator_Private()
@ -711,6 +715,12 @@ namespace NSCSS
if (L"xmp" == wsNodeName || L"nobr" == wsNodeName)
return L"pre";
if (L"ol" == wsNodeName)
return L"ul";
if (L"fieldset" == wsNodeName)
return L"textarea";
return wsNodeName;
}

View File

@ -16,8 +16,9 @@ namespace HTML
#define ADD_TAG(strName, enumName) {strName, HTML_TAG(enumName)}
#define SKIP_TAG SCRIPT
#define UNKNOWN_TAG GumboTag::GUMBO_TAG_UNKNOWN
#define HtmlTag GumboTag
const std::map<std::wstring, HtmlTag> m_HTML_TAGS
const static std::map<std::wstring, HtmlTag> m_HTML_TAGS
{
ADD_TAG(L"a", A),
ADD_TAG(L"abbr", ABBR),
@ -151,6 +152,7 @@ const std::map<std::wstring, HtmlTag> m_HTML_TAGS
ADD_TAG(L"svg", SVG)
};
inline std::wstring GetArgumentValue(XmlUtils::CXmlLiteReader& oLiteReader, const std::wstring& wsArgumentName, const std::wstring& wsDefaultValue = L"");
inline bool CheckArgumentMath(const std::wstring& wsNodeName, const std::wstring& wsStyleName);
inline HtmlTag GetHtmlTag(const std::wstring& wsStrTag);
@ -168,11 +170,18 @@ CHTMLReader::CHTMLReader()
pInterpretator->SetCSSCalculator(&m_oCSSCalculator);
m_pInterpretator = pInterpretator;
m_mTags[HTML_TAG(A)] = std::make_shared<TAnchor<COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(ABBR)] = std::make_shared<TAnchor<COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(BR)] = std::make_shared<TBreak<COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(DIV)] = std::make_shared<TDivision<COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(IMG)] = std::make_shared<TImage<COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(A)] = std::make_shared<TAnchor <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(ABBR)] = std::make_shared<TAnchor <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(BR)] = std::make_shared<TBreak <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(DIV)] = std::make_shared<TDivision <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(IMG)] = std::make_shared<TImage <COOXMLInterpretator>>(pInterpretator, &m_oLightReader);
m_mTags[HTML_TAG(FONT)] = std::make_shared<TFont <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(INPUT)] = std::make_shared<TInput <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(BASEFONT)] = std::make_shared<TBaseFont <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(BLOCKQUOTE)] = std::make_shared<TBlockquote <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(HR)] = std::make_shared<THorizontalRule<COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(UL)] = std::make_shared<TList <COOXMLInterpretator>>(pInterpretator);
m_mTags[HTML_TAG(LI)] = std::make_shared<TListElement <COOXMLInterpretator>>(pInterpretator);
std::shared_ptr<ITag> oIgnoredTag{std::make_shared<TEmptyTag>()};
@ -510,7 +519,7 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
}
case HTML_TAG(BR):
{
bResult = ReadBreak(arSelectors);
bResult = ReadEmptyTag(HTML_TAG(BR), arSelectors);
break;
}
case HTML_TAG(CENTER):
@ -546,12 +555,13 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
bResult = ReadDefaultTag(HTML_TAG(S), arSelectors);
break;
}
// case HTML_TAG(FONT):
// {
// bResult = m_pInterpretator->ReadFont(oXml, sSelectors, oTS);
// break;
// }
case HTML_TAG(FONT):
{
bResult = ReadDefaultTag(HTML_TAG(FONT), arSelectors);
break;
}
case HTML_TAG(IMG):
case HTML_TAG(SVG):
{
bResult = ReadDefaultTag(HTML_TAG(IMG), arSelectors);
break;
@ -578,23 +588,11 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
bResult = ReadDefaultTag(HTML_TAG(SUP), arSelectors);
break;
}
// case HTML_TAG(SVG):
// {
// m_pInterpretator->readSVG(oXml, sSelectors, oTS);
// wrP(oXml, sSelectors, oTS);
// bResult = readSVG(m_oLightReader.GetOuterXml());
// if (bResult)
// ImageRels(oXml, -1, L"", L"png");
// break;
// }
// case HTML_TAG(INPUT):
// {
// bResult = readInput(oXml, sSelectors, oTS);
// break;
// }
case HTML_TAG(INPUT):
{
bResult = ReadDefaultTag(HTML_TAG(INPUT), arSelectors);
break;
}
case HTML_TAG(CANVAS):
case HTML_TAG(VIDEO):
case HTML_TAG(MATH):
@ -624,11 +622,11 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
bResult = ReadDefaultTag(HTML_TAG(PRE), arSelectors);
break;
}
// case HTML_TAG(BASEFONT):
// {
// bResult = ReadBasefont(oXml, sSelectors, oTS);
// break;
// }
case HTML_TAG(BASEFONT):
{
bResult = ReadDefaultTag(HTML_TAG(BASEFONT), arSelectors);
break;
}
case HTML_TAG(BUTTON):
case HTML_TAG(LABEL):
case HTML_TAG(DATA):
@ -678,11 +676,11 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
bResult = ReadDefaultTag(HTML_TAG(DIV), arSelectors);
break;
}
// case HTML_TAG(BLOCKQUOTE):
// {
// bResult = ReadBlockquote(&oXmlData, sSelectors, oTS);
// break;
// }
case HTML_TAG(BLOCKQUOTE):
{
bResult = ReadDefaultTag(HTML_TAG(BLOCKQUOTE), arSelectors);
break;
}
case HTML_TAG(ARTICLE):
case HTML_TAG(HEADER):
case HTML_TAG(MAIN):
@ -703,22 +701,22 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
bResult = ReadStream(arSelectors);
break;
}
// case HTML_TAG(HR):
// {
// bResult = ReadHr(&oXmlData, sSelectors, oTS);
// break;
// }
// case HTML_TAG(LI):
// {
// bResult = ReadListElement(&oXmlData, sSelectors, oTS);
// break;
// }
// case HTML_TAG(OL):
// case HTML_TAG(UL):
// {
// bResult = ReadList(&oXmlData, sSelectors, oTS);
// break;
// }
case HTML_TAG(HR):
{
bResult = ReadEmptyTag(HTML_TAG(HR), arSelectors);
break;
}
case HTML_TAG(LI):
{
bResult = ReadDefaultTag(HTML_TAG(LI), arSelectors);
break;
}
case HTML_TAG(OL):
case HTML_TAG(UL):
{
bResult = ReadDefaultTag(HTML_TAG(OL), arSelectors);
break;
}
// case HTML_TAG(MENU):
// case HTML_TAG(SELECT):
// case HTML_TAG(DATALIST):
@ -733,22 +731,22 @@ bool CHTMLReader::ReadInside(std::vector<NSCSS::CNode>& arSelectors)
bResult = ReadDefaultTag(HTML_TAG(PRE), arSelectors);
break;
}
// case HTML_TAG(TABLE):
// {
// bResult = ParseTable(&oXmlData, sSelectors, oTS);
// break;
// }
case HTML_TAG(TABLE):
{
bResult = ReadTable(arSelectors);
break;
}
// case HTML_TAG(RUBY):
// {
// bResult = ParseRuby(&oXmlData, sSelectors, oTS);
// break;
// }
// case HTML_TAG(TEXTAREA):
// case HTML_TAG(FIELDSET):
// {
// bResult = ReadTextarea(&oXmlData, sSelectors, oTS);
// break;
// }
// case HTML_TAG(TEXTAREA):
// case HTML_TAG(FIELDSET):
// {
// bResult = ReadStream(arSelectors);
// break;
// }
// case HTML_TAG(DETAILS):
// {
// bResult = ReadDetails(&oXmlData, sSelectors, oTS);
@ -805,12 +803,140 @@ bool CHTMLReader::ReadAnchor(std::vector<NSCSS::CNode>& arSelectors)
return true;
}
bool CHTMLReader::ReadBreak(const std::vector<NSCSS::CNode>& arSelectors)
bool CHTMLReader::ReadTable(std::vector<NSCSS::CNode>& arSelectors)
{
if (!m_mTags[HTML_TAG(BR)]->Open(arSelectors))
if(m_oLightReader.IsEmptyNode())
return false;
m_mTags[HTML_TAG(BR)]->Close(arSelectors);
// if (HTML_TAG(TABLE) == m_oState.m_eLastElement)
// WriteEmptyParagraph(oXml, true);
CTable oTable;
CTextSettings oTextSettings{oTS};
oTextSettings.sPStyle.clear();
NSCSS::CCompiledStyle *pStyle = sSelectors.back().m_pCompiledStyle;
//Table styles
std::wstring wsFrame;
for (const std::pair<std::wstring, std::wstring>& oArgument : sSelectors.back().m_mAttributes)
{
if (L"border" == oArgument.first)
{
const int nWidth = NSStringFinder::ToInt(oArgument.second);
if (0 < nWidth)
{
oTable.SetRules(L"all");
if (!pStyle->m_oBorder.Empty())
continue;
pStyle->m_oBorder.SetStyle(L"outset", 0, true);
pStyle->m_oBorder.SetWidth(nWidth, NSCSS::UnitMeasure::Point, 0, true);
pStyle->m_oBorder.SetColor(L"auto", 0, true);
}
else if (pStyle->m_oBorder.Empty())
{
pStyle->m_oBorder.SetNone(0, true);
oTable.SetRules(L"none");
}
}
else if (L"cellpadding" == oArgument.first)
pStyle->m_oPadding.SetValues(oArgument.second + L"px", 0, true);
else if (L"rules" == oArgument.first)
oTable.SetRules(oArgument.second);
else if (L"frame" == oArgument.first)
wsFrame = oArgument.second;
}
if (!wsFrame.empty() && pStyle->m_oBorder.Empty())
{
#define SetDefaultBorderSide(side) \
pStyle->m_oBorder.SetStyle##side(L"solid", 0, true); \
pStyle->m_oBorder.SetWidth##side(1, NSCSS::UnitMeasure::Point, 0, true); \
pStyle->m_oBorder.SetColor##side(L"black", 0, true)
if (NSStringFinder::Equals(L"border", wsFrame))
{
SetDefaultBorderSide();
}
else if (NSStringFinder::Equals(L"above", wsFrame))
{
SetDefaultBorderSide(TopSide);
}
else if (NSStringFinder::Equals(L"below", wsFrame))
{
SetDefaultBorderSide(BottomSide);
}
else if (NSStringFinder::Equals(L"hsides", wsFrame))
{
SetDefaultBorderSide(TopSide);
SetDefaultBorderSide(BottomSide);
}
else if (NSStringFinder::Equals(L"vsides", wsFrame))
{
SetDefaultBorderSide(LeftSide);
SetDefaultBorderSide(RightSide);
}
else if (NSStringFinder::Equals(L"rhs", wsFrame))
{
SetDefaultBorderSide(RightSide);
}
else if (NSStringFinder::Equals(L"lhs", wsFrame))
{
SetDefaultBorderSide(LeftSide);
}
}
if (pStyle->m_oBorder.GetCollapse() == NSCSS::NSProperties::BorderCollapse::Collapse)
oTable.SetCellSpacing(0);
else if (sSelectors.back().m_mAttributes.end() != sSelectors.back().m_mAttributes.find(L"cellspacing"))
oTable.SetCellSpacing(NSStringFinder::ToInt(sSelectors.back().m_mAttributes[L"cellspacing"]));
else if (pStyle->m_oBorder.GetCollapse() == NSCSS::NSProperties::BorderCollapse::Separate)
oTable.SetCellSpacing(15);
oTable.SetWidth(pStyle->m_oDisplay.GetWidth());
oTable.SetBorder(pStyle->m_oBorder);
oTable.SetPadding(pStyle->m_oPadding);
oTable.SetMargin(pStyle->m_oMargin);
oTable.SetAlign(pStyle->m_oDisplay.GetHAlign().ToWString());
//------
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDeath))
{
const std::wstring sName = m_oLightReader.GetName();
GetSubClass(oXml, sSelectors);
if(sName == L"caption")
ParseTableCaption(oTable, sSelectors, oTS);
if(sName == L"thead")
ParseTableRows(oTable, sSelectors, oTextSettings, ERowParseMode::ParseModeHeader);
if(sName == L"tbody")
ParseTableRows(oTable, sSelectors, oTextSettings, ERowParseMode::ParseModeBody);
else if(sName == L"tfoot")
ParseTableRows(oTable, sSelectors, oTextSettings, ERowParseMode::ParseModeFoother);
else if (sName == L"colgroup")
ParseTableColspan(oTable);
arSelectors.pop_back();
}
oTable.Shorten();
oTable.CompleteTable();
oTable.ConvertToOOXML(*oXml);
return true;
}
bool CHTMLReader::ReadEmptyTag(UINT unTag, const std::vector<NSCSS::CNode>& arSelectors)
{
if (!m_mTags[unTag]->Open(arSelectors))
return false;
m_mTags[unTag]->Close(arSelectors);
return true;
}

View File

@ -9,8 +9,6 @@
namespace HTML
{
#define HtmlTag GumboTag
class CHTMLReader
{
XmlUtils::CXmlLiteReader m_oLightReader; // SAX Reader
@ -53,8 +51,8 @@ private:
bool ReadText(std::vector<NSCSS::CNode>& arSelectors);
bool ReadAnchor(std::vector<NSCSS::CNode>& arSelectors);
bool ReadBreak(const std::vector<NSCSS::CNode>& arSelectors);
bool ReadTable(std::vector<NSCSS::CNode>& arSelectors);
bool ReadEmptyTag(UINT unTag, const std::vector<NSCSS::CNode>& arSelectors);
bool ReadDefaultTag(UINT unTag, std::vector<NSCSS::CNode>& arSelectors);
void GetSubClass(std::vector<NSCSS::CNode>& arSelectors);

View File

@ -47,7 +47,7 @@ inline void replace_all(std::wstring& s, const std::wstring& s1, const std::wstr
inline std::wstring EncodeXmlString(std::wstring wsString);
COOXMLInterpretator::COOXMLInterpretator()
: m_nFootnoteId(1), m_nHyperlinkId(1), m_nNumberingId(1), m_nId(1), m_nShapeId(1), m_pFonts(nullptr)
: m_nFootnoteId(1), m_nHyperlinkId(1), m_nNumberingId(1), m_nId(1), m_nShapeId(1), m_bWasDivs(false), m_pFonts(nullptr)
{
m_oPageData.SetWidth (DEFAULT_PAGE_WIDTH, NSCSS::UnitMeasure::Twips, 0, true);
m_oPageData.SetHeight(DEFAULT_PAGE_HEIGHT, NSCSS::UnitMeasure::Twips, 0, true);
@ -346,7 +346,7 @@ void COOXMLInterpretator::End(const std::wstring& wsDst)
}
// webSettings.xml
if (!m_mDivs.empty())
if (!m_bWasDivs)
m_oWebSettings.WriteString(L"</w:divs>");
m_oWebSettings.WriteString(L"</w:webSettings>");
@ -587,7 +587,7 @@ std::wstring COOXMLInterpretator::WritePPr(const std::vector<NSCSS::CNode>& arSe
if (sPStyle.empty() && !ElementInTable(arSelectors))
sPStyle = L"normal-web";
if (sPStyle.empty() /*&& oTS.sPStyle.empty() && 0 > oTS.nLi*/)
if (sPStyle.empty() && m_arDivId.empty() /*&& oTS.sPStyle.empty() && 0 > oTS.nLi*/)
return L"";
// m_oXmlStyle.WriteLitePStyle(oTS.oAdditionalStyle);
@ -622,6 +622,8 @@ std::wstring COOXMLInterpretator::WritePPr(const std::vector<NSCSS::CNode>& arSe
m_arStates.top().m_pCurrentDocument->WriteString(L"<w:numPr><w:ilvl w:val=\"" + std::to_wstring(nLiLevel) + L"\"/><w:numId w:val=\"" +
(bNumberingLi ? L"1" : std::to_wstring(m_nNumberingId)) + L"\"/></w:numPr>");
if (!m_arDivId.empty())
m_arStates.top().m_pCurrentDocument->WriteString(L"<w:divId w:val=\"" + m_arDivId.top() + L"\"/>");
// m_pCurrentDocument->WriteString(oTS.sPStyle + sPSettings);
m_arStates.top().m_pCurrentDocument->WriteNodeEnd(L"w:pPr");
m_arStates.top().m_bWasPStyle = true;
@ -1036,6 +1038,24 @@ void COOXMLInterpretator::UpdatePageStyle(const std::vector<NSCSS::CNode>& arSel
m_pStylesCalculator->CalculatePageStyle(m_oPageData, arSelectors);
}
void COOXMLInterpretator::SetBaseFont(const std::wstring& wsFontStyles)
{
if (nullptr != m_pStylesCalculator)
m_pStylesCalculator->AddStyles(wsFontStyles);
}
void COOXMLInterpretator::SetDivId(const std::wstring& wsDivId)
{
m_arDivId.push(wsDivId);
m_bWasDivs = true;
}
void COOXMLInterpretator::RollBackDivId()
{
if (!m_arDivId.empty())
m_arDivId.pop();
}
std::wstring COOXMLInterpretator::FindFootnote(const std::wstring& wsId)
{
const std::map<std::wstring, std::wstring>::const_iterator itFound{m_mFootnotes.find(wsId)};
@ -1094,6 +1114,11 @@ XmlString& COOXMLInterpretator::GetCurrentDocument()
return *m_arStates.top().m_pCurrentDocument;
}
const NSCSS::NSProperties::CPage* COOXMLInterpretator::GetPageData() const
{
return &m_oPageData;
}
NSFonts::IApplicationFonts* COOXMLInterpretator::GetFonts()
{
if (nullptr == m_pFonts)

View File

@ -107,11 +107,13 @@ class COOXMLInterpretator : public IHTMLInterpretator
int m_nId; // ID остальные элементы
int m_nShapeId; // Id shape's
std::stack<std::wstring> m_arDivId;
bool m_bWasDivs;
std::map<std::wstring, std::wstring> m_mFootnotes; // Сноски
std::map<std::wstring, UINT> m_mBookmarks; // Закладки
using anchors_map = std::map<std::wstring, std::wstring>;
anchors_map m_mAnchors; // Map якорей с индивидуальными id
std::map<std::wstring, UINT> m_mDivs; // Div элементы
NSFonts::IApplicationFonts* m_pFonts; // Необходимо для оптимизации работы со шрифтами
public:
@ -165,6 +167,9 @@ public:
std::wstring GetStyle(const NSCSS::CCompiledStyle& oStyle, bool bParagraphStyle);
void UpdatePageStyle(const std::vector<NSCSS::CNode>& arSelectors);
void SetBaseFont(const std::wstring& wsFontStyles);
void SetDivId(const std::wstring& wsDivId);
void RollBackDivId();
std::wstring FindFootnote(const std::wstring& wsId);
void OpenFootnote(const std::wstring& wsFootnoteID);
@ -179,6 +184,7 @@ public:
XmlString& GetWebSettingsXml();
XmlString& GetCurrentDocument();
const NSCSS::NSProperties::CPage* GetPageData() const;
NSFonts::IApplicationFonts* GetFonts();
std::wstring GetMediaDir() const;

View File

@ -67,6 +67,12 @@ CREATE_TAG(TPreformatted);
CREATE_TAG(THeader);
CREATE_TAG(TDivision);
CREATE_TAG(TImage);
CREATE_TAG(TFont);
CREATE_TAG(TInput);
CREATE_TAG(TBaseFont);
CREATE_TAG(TBlockquote);
CREATE_TAG(THorizontalRule);
CREATE_TAG(TList);
CREATE_TAG(TListElement);
}
#endif // HTMLTAGS_H

View File

@ -1,19 +1,817 @@
#include "OOXMLTags.h"
#include "../src/StringFinder.h"
#include "../../Common/Network/FileTransporter/include/FileTransporter.h"
#include "../../DesktopEditor/xml/include/xmlutils.h"
#include "../../DesktopEditor/raster/BgraFrame.h"
#include "../../DesktopEditor/graphics/pro/Graphics.h"
#include "../../DesktopEditor/common/ProcessEnv.h"
#include "../../DesktopEditor/common/Base64.h"
#include "../../DesktopEditor/common/File.h"
#include "../../DesktopEditor/common/ProcessEnv.h"
#include "../../DesktopEditor/common/Path.h"
namespace HTML
{
bool IsSVG(const std::wstring& wsExtention)
inline bool ElementInTable(const std::vector<NSCSS::CNode>& arSelectors);
inline bool NotValidExtension(const std::wstring& sExtention);
inline bool IsSVG(const std::wstring& wsExtention);
bool ReadSVG(const std::wstring& wsSvg, NSFonts::IApplicationFonts* pFonts, const std::wstring& wsTempDir, const std::wstring& wsImagePath);
bool ReadBase64(const std::wstring& wsSrc, const std::wstring& wsImagePath, NSFonts::IApplicationFonts* pFonts, const std::wstring& wsTempDir, std::wstring& wsExtention);
bool GetStatusUsingExternalLocalFiles();
bool CanUseThisPath(const std::wstring& wsPath, const std::wstring& wsSrcPath, const std::wstring& wsCorePath, bool bIsAllowExternalLocalFiles);
bool CopyImage(std::wstring wsImageSrc, const std::wstring& wsSrc, const std::wstring& wsDst, bool bIsAllowExternalLocalFiles);
bool UpdateImageData(const std::wstring& wsImagePath, TImageData& oImageData);
const static double HTML_FONTS[7] = {7.5, 10, 12, 13.5, 18, 24, 36};
TAnchor<COOXMLInterpretator>::TAnchor(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TAnchor<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
return L"svg" == wsExtention || L"svg+xml" == wsExtention;
if (!ValidInterpretator())
return false;
std::wstring wsRef, wsAlt, wsName;
bool bCross = false;
if (arSelectors.back().GetAttributeValue(L"href", wsRef) && wsRef.find('#') != std::wstring::npos)
bCross = true;
if (arSelectors.back().GetAttributeValue(L"name", wsName))
m_pInterpretator->WriteBookmark(wsName);
arSelectors.back().GetAttributeValue(L"alt", wsAlt);
if (!m_pInterpretator->OpenP())
m_pInterpretator->CloseR();
else
m_pInterpretator->WritePPr(arSelectors);
if (bCross)
m_pInterpretator->OpenCrossHyperlink(wsRef, arSelectors);
else
{
std::wstring wsTooltip(wsRef);
arSelectors.back().GetAttributeValue(L"title", wsTooltip);
m_pInterpretator->OpenExternalHyperlink(wsRef, wsTooltip, arSelectors);
}
return true;
}
bool NotValidExtension(const std::wstring& sExtention)
void TAnchor<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return;
bool bCross = false;
std::wstring wsFootnote;
if (arSelectors.back().m_wsStyle.find(L"mso-footnote-id") != std::wstring::npos)
wsFootnote = arSelectors.back().m_wsStyle.substr(arSelectors.back().m_wsStyle.rfind(L':') + 1);
else
{
if (arSelectors.back().GetAttributeValue(L"epub:type", wsFootnote) && wsFootnote.find(L"noteref"))
wsFootnote = L"href";
}
std::wstring wsRef;
if (arSelectors.back().GetAttributeValue(L"href", wsRef))
{
if(wsRef.find('#') != std::wstring::npos)
bCross = true;
}
if (bCross)
{
if (wsFootnote == L"href")
wsFootnote = wsRef.substr(wsRef.find('#') + 1);
m_pInterpretator->CloseCrossHyperlink(arSelectors, wsFootnote, wsRef);
}
else
m_pInterpretator->CloseExternalHyperlink();
}
TAbbr<COOXMLInterpretator>::TAbbr(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TAbbr<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
std::wstring wsTitle;
if (!arSelectors.back().GetAttributeValue(L"title", wsTitle))
return false;
m_pInterpretator->WritePPr(arSelectors);
XmlString* pCurrentDocument{&m_pInterpretator->GetCurrentDocument()};
pCurrentDocument->WriteString(L"<w:r><w:fldChar w:fldCharType=\"begin\"/></w:r><w:r><w:instrText>HYPERLINK \\l \"" + m_pInterpretator->AddLiteBookmark() + L"\" \\o \"");
pCurrentDocument->WriteEncodeXmlString(wsTitle);
pCurrentDocument->WriteString(L"\"</w:instrText></w:r>");
pCurrentDocument->WriteString(L"<w:r><w:fldChar w:fldCharType=\"separate\"/></w:r>");
return true;
}
void TAbbr<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return;
m_pInterpretator->GetCurrentDocument().WriteString(L"<w:r><w:fldChar w:fldCharType=\"end\"/></w:r>");
}
TBreak<COOXMLInterpretator>::TBreak(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TBreak<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
m_pInterpretator->Break(arSelectors);
return true;
}
void TBreak<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{}
TDivision<COOXMLInterpretator>::TDivision(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TDivision<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
m_pInterpretator->UpdatePageStyle(arSelectors);
UINT unMsoFootnote = 0;
if (L"footnote" == arSelectors.back().GetAttributeValue(L"epub:type"))
++unMsoFootnote;
if (std::wstring::npos != arSelectors.back().m_wsStyle.find(L"mso-element:footnote"))
++unMsoFootnote;
std::wstring wsFootnoteID;
if (!arSelectors.back().m_wsId.empty())
{
wsFootnoteID = m_pInterpretator->FindFootnote(arSelectors.back().m_wsId);
if (!wsFootnoteID.empty())
++unMsoFootnote;
if (unMsoFootnote >= 2 && !wsFootnoteID.empty())
{
m_pInterpretator->OpenFootnote(wsFootnoteID);
m_pInterpretator->SetCurrentDocument(&m_pInterpretator->GetNotesXml());
}
}
m_arFootnoteIDs.push(unMsoFootnote);
return true;
}
void TDivision<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator() || m_arFootnoteIDs.empty())
return;
if (m_arFootnoteIDs.top() >= 2)
{
m_pInterpretator->CloseFootnote();
m_pInterpretator->RollBackState();
}
m_arFootnoteIDs.pop();
}
TImage<COOXMLInterpretator>::TImage(COOXMLInterpretator* pInterpretator, XmlUtils::CXmlLiteReader* pXmlReader)
: TTag(pInterpretator), m_pXmlReader(pXmlReader)
{}
bool TImage<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
if (L"svg" == arSelectors.back().m_wsName)
{
if (nullptr == m_pXmlReader)
return false;
const std::wstring wsImagePath{m_pInterpretator->GetMediaDir() + L'i' + std::to_wstring(m_arrImages.size()) + L".png"};
if (!ReadSVG(m_pXmlReader->GetOuterXml(), m_pInterpretator->GetFonts(), m_pInterpretator->GetTempDir(), wsImagePath))
return false;
TImageData oNewImageData;
if (!UpdateImageData(wsImagePath, oNewImageData))
return false;
m_pInterpretator->WritePPr(arSelectors);
m_pInterpretator->WriteImage(oNewImageData, std::to_wstring(m_arrImages.size()));
return true;
}
const std::wstring wsAlt{arSelectors.back().GetAttributeValue(L"alt")};
std::wstring wsSrc{arSelectors.back().GetAttributeValue(L"src")};
TImageData oImageData;
std::wstring wsTempValue;
NSCSS::NSProperties::CDigit oTempDigit;
#define GET_UNIT_DATA(variable_data, data_variable)\
if (NSCSS::UnitMeasure::None == data_variable.GetUnitMeasure())\
variable_data = static_cast<UINT>(NSCSS::CUnitMeasureConverter::ConvertPx(data_variable.ToDouble(), NSCSS::Inch, 96) * 914400);\
else\
variable_data = static_cast<UINT>(data_variable.ToDouble(NSCSS::Inch) * 914400)
#define READ_IMAGE_DATA(name_data, variable_data)\
if (arSelectors.back().GetAttributeValue(name_data, wsTempValue))\
{\
if (oTempDigit.SetValue(wsTempValue))\
{\
GET_UNIT_DATA(variable_data, oTempDigit);\
}\
}
READ_IMAGE_DATA(L"width", oImageData.m_unWidth);
READ_IMAGE_DATA(L"height", oImageData.m_unHeight);
READ_IMAGE_DATA(L"hspace", oImageData.m_nHSpace);
READ_IMAGE_DATA(L"vspace", oImageData.m_nVSpace);
if (nullptr != arSelectors.back().m_pCompiledStyle)
{
oTempDigit = arSelectors.back().m_pCompiledStyle->m_oDisplay.GetWidth();
if (0 == oImageData.m_unWidth && !oTempDigit.Empty())
{
GET_UNIT_DATA(oImageData.m_unWidth, oTempDigit);
}
oTempDigit = arSelectors.back().m_pCompiledStyle->m_oDisplay.GetHeight();
if (0 == oImageData.m_unHeight && !oTempDigit.Empty())
{
GET_UNIT_DATA(oImageData.m_unHeight, oTempDigit);
}
}
if (wsSrc.empty())
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
bool bRes = false;
std::wstring wsExtention;
const std::wstring wsImagePath{m_pInterpretator->GetMediaDir() + L'i' + std::to_wstring(m_arrImages.size())};
// Предполагаем картинку в Base64
if (wsSrc.length() > 4 && wsSrc.substr(0, 4) == L"data" && wsSrc.find(L"/", 4) != std::wstring::npos)
bRes = ReadBase64(wsSrc, wsImagePath, m_pInterpretator->GetFonts(), m_pInterpretator->GetTempDir(), wsExtention);
const bool bIsAllowExternalLocalFiles = GetStatusUsingExternalLocalFiles();
if (!bRes && (wsSrc.length() <= 7 || L"http" != wsSrc.substr(0, 4)))
{
wsSrc = NSSystemPath::ShortenPath(wsSrc);
if (!CanUseThisPath(wsSrc, m_pInterpretator->GetSrcPath(), m_pInterpretator->GetCorePath(), bIsAllowExternalLocalFiles))
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
}
// Проверка расширения
if (!bRes)
{
wsExtention = NSFile::GetFileExtention(wsSrc);
std::transform(wsExtention.begin(), wsExtention.end(), wsExtention.begin(), tolower);
std::wstring::const_iterator itFound = std::find_if(wsExtention.cbegin(), wsExtention.cend(), [](wchar_t wChar){ return !iswalpha(wChar) && L'+' != wChar; });
if (wsExtention.cend() != itFound)
wsExtention.erase(itFound, wsExtention.cend());
}
const std::wstring wsBasePath{m_pInterpretator->GetBasePath()};
// Предполагаем картинку в сети
if (!bRes &&
((!wsBasePath.empty() && wsBasePath.length() > 4 && wsBasePath.substr(0, 4) == L"http") ||
(wsSrc.length() > 4 && wsSrc.substr(0, 4) == L"http")))
{
const std::wstring wsDst = wsImagePath + L'.' + ((!wsExtention.empty()) ? wsExtention : L"png");
// Проверка gc_allowNetworkRequest предполагается в kernel_network
NSNetwork::NSFileTransport::CFileDownloader oDownloadImg(m_pInterpretator->GetBasePath() + wsSrc, false);
oDownloadImg.SetFilePath(wsDst);
bRes = oDownloadImg.DownloadSync();
if (!bRes)
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
if (IsSVG(wsExtention))
{
std::wstring wsFileData;
if (!NSFile::CFileBinary::ReadAllTextUtf8(wsDst, wsFileData) ||
!ReadSVG(wsFileData, m_pInterpretator->GetFonts(), m_pInterpretator->GetTempDir(), wsImagePath))
bRes = false;
NSFile::CFileBinary::Remove(wsDst);
wsExtention = L"png";
}
else if (wsExtention.empty())
{
//TODO:: лучше узнавать формат изображения из содержимого
wsExtention = L"png";
}
}
int nImageId = -1;
if (!bRes)
{
if (NotValidExtension(wsExtention))
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
// Проверка на повтор
std::vector<std::wstring>::iterator nFind = std::find(m_arrImages.begin(), m_arrImages.end(), wsSrc);
if (nFind != m_arrImages.end())
{
bRes = true;
nImageId = nFind - m_arrImages.begin();
}
}
// Предполагаем картинку по локальному пути
if (!bRes)
{
const std::wstring wsDst = wsImagePath + L'.' + wsExtention;
if (!m_pInterpretator->GetBasePath().empty())
{
if (!bRes)
bRes = CopyImage(NSSystemPath::Combine(m_pInterpretator->GetBasePath(), wsSrc), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
if (!bRes)
bRes = CopyImage(NSSystemPath::Combine(m_pInterpretator->GetSrcPath(), NSSystemPath::Combine(m_pInterpretator->GetBasePath(), wsSrc)), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
}
if (!bRes)
bRes = CopyImage(NSSystemPath::Combine(m_pInterpretator->GetSrcPath(), wsSrc), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
if (!bRes)
bRes = CopyImage(m_pInterpretator->GetSrcPath() + L"/" + NSFile::GetFileName(wsSrc), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
if (!bRes)
bRes = CopyImage(wsSrc, m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
}
if (!bRes)
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
else
{
m_arrImages.push_back(wsSrc);
m_pInterpretator->WritePPr(arSelectors);
const std::wstring wsImageID{std::to_wstring(m_arrImages.size())};
if (nImageId < 0)
{
m_pInterpretator->WriteImageRels(wsImageID, wsImageID + L'.' + wsExtention);
m_arrImages.push_back(wsSrc);
}
if (!oImageData.ZeroSize())
{
m_pInterpretator->WriteImage(oImageData, wsImageID);
return true;
}
TImageData oNewImageData{oImageData};
if (!UpdateImageData(wsImagePath + L'.' + wsExtention, oNewImageData))
return false;
m_pInterpretator->WriteImage(oNewImageData, wsImageID);
}
return true;
}
void TImage<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{}
TFont<COOXMLInterpretator>::TFont(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TFont<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
std::wstring wsValue;
if (arSelectors.back().GetAttributeValue(L"color", wsValue))
arSelectors.back().m_pCompiledStyle->m_oText.SetColor(wsValue, arSelectors.size());
if (arSelectors.back().GetAttributeValue(L"face", wsValue))
arSelectors.back().m_pCompiledStyle->m_oFont.SetFamily(wsValue, arSelectors.size());
if (arSelectors.back().GetAttributeValue(L"size", wsValue))
{
int nSize = 3;
if(!wsValue.empty())
{
// if(wsValue.front() == L'+')
// nSize += NSStringFinder::ToInt(wsValue.substr(1));
// else if(wsValue.front() == L'-')
// nSize -= NSStringFinder::ToInt(wsValue.substr(1));
// else
// nSize = NSStringFinder::ToInt(wsValue);
}
if (nSize < 1 || nSize > 7)
nSize = 3;
arSelectors.back().m_pCompiledStyle->m_oFont.SetSize(HTML_FONTS[nSize - 1], NSCSS::UnitMeasure::Point, arSelectors.size());
}
return true;
}
void TFont<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{}
TInput<COOXMLInterpretator>::TInput(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TInput<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
std::wstring wsValue{arSelectors.back().GetAttributeValue(L"value")};
const std::wstring wsAlt{arSelectors.back().GetAttributeValue(L"alt")},
wsType{arSelectors.back().GetAttributeValue(L"type")};
if(wsType == L"hidden")
return false;
if(wsValue.empty())
wsValue = wsAlt;
if(!wsValue.empty())
{
m_pInterpretator->WritePPr(arSelectors);
m_pInterpretator->OpenR();
m_pInterpretator->WriteRPr(m_pInterpretator->GetCurrentDocument(), arSelectors);
m_pInterpretator->OpenT();
m_pInterpretator->GetCurrentDocument().WriteEncodeXmlString(wsValue + L' ');
m_pInterpretator->CloseT();
m_pInterpretator->CloseR();
}
return true;
}
void TInput<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{}
TBaseFont<COOXMLInterpretator>::TBaseFont(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TBaseFont<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
std::wstring wsFontStyles, wsValue;
if (arSelectors.back().GetAttributeValue(L"face", wsValue))
wsFontStyles += L"font-family:" + wsValue + L';';
if (arSelectors.back().GetAttributeValue(L"size", wsValue))
{
wsFontStyles += L"font-size:";
switch(NSStringFinder::ToInt(wsValue, 3))
{
case 1: wsFontStyles += L"7.5pt;"; break;
case 2: wsFontStyles += L"10pt;"; break;
default:
case 3: wsFontStyles += L"12pt;"; break;
case 4: wsFontStyles += L"13.5pt;"; break;
case 5: wsFontStyles += L"18pt;"; break;
case 6: wsFontStyles += L"24pt;"; break;
case 7: wsFontStyles += L"36pt;"; break;
}
}
if (arSelectors.back().GetAttributeValue(L"color", wsValue))
wsFontStyles += L"text-color:" + wsValue + L';';
if (wsFontStyles.empty())
return false;
m_pInterpretator->SetBaseFont(L"*{" + wsFontStyles + L'}');
return true;
}
void TBaseFont<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{}
TBlockquote<COOXMLInterpretator>::TBlockquote(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TBlockquote<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
const std::wstring wsKeyWord{arSelectors.back().m_wsName};
std::map<std::wstring, UINT>::const_iterator itFound = m_mDivs.find(wsKeyWord);
if (m_mDivs.end() != itFound)
{
m_pInterpretator->SetDivId(std::to_wstring(itFound->second));
return true;
}
const std::wstring wsId{std::to_wstring(m_mDivs.size() + 1)};
XmlString &oWebSettings{m_pInterpretator->GetWebSettingsXml()};
if (m_mDivs.empty())
oWebSettings.WriteString(L"<w:divs>");
NSCSS::CCompiledStyle *pStyle = arSelectors.back().m_pCompiledStyle;
const bool bInTable = ElementInTable(arSelectors);
INT nMarLeft = (!bInTable) ? 720 : 0;
INT nMarRight = (!bInTable) ? 720 : 0;
INT nMarTop = (!bInTable) ? 100 : 0;
INT nMarBottom = (!bInTable) ? 100 : 0;
const NSCSS::NSProperties::CPage *pPageData{m_pInterpretator->GetPageData()};
if (!pStyle->m_oMargin.GetLeft().Empty() && !pStyle->m_oMargin.GetLeft().Zero())
nMarLeft = pStyle->m_oMargin.GetLeft().ToInt(NSCSS::Twips, pPageData->GetWidth().ToInt(NSCSS::Twips));
if (!pStyle->m_oMargin.GetRight().Empty() && !pStyle->m_oMargin.GetRight().Zero())
nMarRight = pStyle->m_oMargin.GetRight().ToInt(NSCSS::Twips, pPageData->GetWidth().ToInt(NSCSS::Twips));
if (!pStyle->m_oMargin.GetTop().Empty() && !pStyle->m_oMargin.GetTop().Zero())
nMarTop = pStyle->m_oMargin.GetTop().ToInt(NSCSS::Twips, pPageData->GetHeight().ToInt(NSCSS::Twips));
if (!pStyle->m_oMargin.GetBottom().Empty() && !pStyle->m_oMargin.GetBottom().Zero())
nMarBottom = pStyle->m_oMargin.GetBottom().ToInt(NSCSS::Twips, pPageData->GetHeight().ToInt(NSCSS::Twips));
if (L"blockquote" == wsKeyWord)
{
oWebSettings.WriteString(L"<w:div w:id=\"" + wsId + L"\">");
oWebSettings.WriteString(L"<w:blockQuote w:val=\"1\"/>");
oWebSettings.WriteString(L"<w:marLeft w:val=\"" + std::to_wstring(nMarLeft) + L"\"/>");
oWebSettings.WriteString(L"<w:marRight w:val=\"" + std::to_wstring(nMarRight) + L"\"/>");
oWebSettings.WriteString(L"<w:marTop w:val=\"" + std::to_wstring(nMarTop) + L"\"/>");
oWebSettings.WriteString(L"<w:marBottom w:val=\"" + std::to_wstring(nMarBottom) + L"\"/>");
oWebSettings.WriteString(L"<w:divBdr>");
oWebSettings.WriteString(L"<w:top w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
oWebSettings.WriteString(L"<w:left w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
oWebSettings.WriteString(L"<w:bottom w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
oWebSettings.WriteString(L"<w:right w:val=\"none\" w:sz=\"0\" w:space=\"0\" w:color=\"auto\"/>");
oWebSettings.WriteString(L"</w:divBdr>");
oWebSettings.WriteString(L"</w:div>");
}
m_mDivs.insert(std::make_pair(wsKeyWord, m_mDivs.size() + 1));
m_pInterpretator->SetDivId(wsId);
return true;
}
void TBlockquote<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return;
m_pInterpretator->RollBackDivId();
}
THorizontalRule<COOXMLInterpretator>::THorizontalRule(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator), m_unShapeId(1)
{}
bool THorizontalRule<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
for (const NSCSS::CNode& item : arSelectors)
{
if (item.m_wsName == L"div" && item.m_wsStyle == L"mso-element:footnote-list")
return false;
}
NSCSS::NSProperties::CDigit oSize, oWidth;
NSCSS::NSProperties::CColor oColor;
bool bShade = true;
std::wstring wsAlign{L"center"};
std::wstring wsValue;
if (arSelectors.back().GetAttributeValue(L"align", wsValue))
{
if (NSStringFinder::Equals(L"left", wsValue))
wsAlign = L"left";
else if (NSStringFinder::Equals(L"right", wsValue))
wsAlign = L"right";
else if (NSStringFinder::Equals(L"center", wsValue))
wsAlign = L"center";
}
if (arSelectors.back().GetAttributeValue(L"color", wsValue))
oColor.SetValue(wsValue);
if (arSelectors.back().GetAttributeValue(L"noshade", wsValue))
bShade = false;
if (arSelectors.back().GetAttributeValue(L"size", wsValue))
oSize.SetValue(wsValue);
if (arSelectors.back().GetAttributeValue(L"width", wsValue))
oWidth.SetValue(wsValue);
XmlString& oCurrentDocument{m_pInterpretator->GetCurrentDocument()};
m_pInterpretator->OpenP();
oCurrentDocument.WriteString(L"<w:pPr><w:jc w:val=\"" + wsAlign + L"\"/></w:pPr>");
m_pInterpretator->OpenR();
const NSCSS::NSProperties::CPage *pPageData{m_pInterpretator->GetPageData()};
const unsigned int unPageWidth{static_cast<unsigned int>((pPageData->GetWidth().ToDouble(NSCSS::Inch) - pPageData->GetMargin().GetLeft().ToDouble(NSCSS::Inch) - pPageData->GetMargin().GetRight().ToDouble(NSCSS::Inch)) * 914400.)};
std::wstring wsWidth;
// width измеряется в px или %
if (!oWidth.Empty())
wsWidth = std::to_wstring(static_cast<int>((NSCSS::UnitMeasure::Percent != oWidth.GetUnitMeasure()) ? (NSCSS::CUnitMeasureConverter::ConvertPx(oWidth.ToDouble(), NSCSS::Inch, 96) * 914400.) : oWidth.ToDouble(NSCSS::Inch, unPageWidth)));
else
wsWidth = std::to_wstring(unPageWidth);
std::wstring wsHeight{L"14288"};
// size измеряется только в px
if (!oSize.Empty())
wsHeight = std::to_wstring(static_cast<int>(NSCSS::CUnitMeasureConverter::ConvertPx(oSize.ToDouble(), NSCSS::Inch, 96) * 914400.));
oCurrentDocument.WriteString(L"<w:rPr><w:noProof/></w:rPr>");
oCurrentDocument.WriteString(L"<mc:AlternateContent><mc:Choice Requires=\"wps\"><w:drawing><wp:inline distT=\"0\" distB=\"0\" distL=\"0\" distR=\"0\">");
oCurrentDocument.WriteString(L"<wp:extent cx=\"" + wsWidth + L"\" cy=\"0\"/>");
oCurrentDocument.WriteString(L"<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>");
oCurrentDocument.WriteString(L"<wp:docPr id=\"" + std::to_wstring(m_unShapeId) + L"\" name=\"Line " + std::to_wstring(m_unShapeId) + L"\"/>"
"<wp:cNvGraphicFramePr/>"
"<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
"<a:graphicData uri=\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\">"
"<wps:wsp>"
"<wps:cNvSpPr/>"
"<wps:spPr>");
oCurrentDocument.WriteString(L"<a:xfrm>"
"<a:off x=\"0\" y=\"0\"/>"
"<a:ext cx=\"" + wsWidth + L"\" cy=\"0\"/>"
"</a:xfrm>"
"<a:custGeom><a:pathLst><a:path>"
"<a:moveTo><a:pt x=\"0\" y=\"0\"/></a:moveTo>"
"<a:lnTo><a:pt x=\"" + wsWidth + L"\" y=\"0\"/></a:lnTo>"
"</a:path></a:pathLst></a:custGeom>"
"<a:ln w=\"" + wsHeight + L"\"><a:solidFill><a:srgbClr val=\"" + ((!oColor.Empty()) ? oColor.ToHEX() : L"808080") + L"\"/></a:solidFill></a:ln>");
if (bShade)
oCurrentDocument.WriteString(L"<a:scene3d><a:camera prst=\"orthographicFront\"/><a:lightRig rig=\"threePt\" dir=\"t\"/></a:scene3d><a:sp3d><a:bevelT prst=\"angle\"/></a:sp3d>");
oCurrentDocument.WriteString(L"</wps:spPr><wps:bodyPr/></wps:wsp></a:graphicData></a:graphic></wp:inline></w:drawing></mc:Choice></mc:AlternateContent>");
m_pInterpretator->CloseP();
++m_unShapeId;
return true;
}
void THorizontalRule<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{}
TList<COOXMLInterpretator>::TList(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator), m_unNumberingId(1)
{}
bool TList<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return false;
m_pInterpretator->CloseP();
//Нумерованный список
if (L"ol" == arSelectors.back().m_wsName)
{
const int nStart{NSStringFinder::ToInt(arSelectors.back().GetAttributeValue(L"start"), 1)};
XmlString& oNumberXml{m_pInterpretator->GetNumberingXml()};
const std::wstring wsStart(std::to_wstring(nStart));
oNumberXml.WriteString(L"<w:abstractNum w:abstractNumId=\"");
oNumberXml.WriteString(std::to_wstring(m_unNumberingId++));
oNumberXml.WriteString(L"\"><w:multiLevelType w:val=\"hybridMultilevel\"/><w:lvl w:ilvl=\"0\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%1.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"709\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"1\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%2.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"1429\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"2\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%3.\"/><w:lvlJc w:val=\"right\"/><w:pPr><w:ind w:left=\"2149\" w:hanging=\"180\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"3\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%4.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2869\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"4\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%5.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"3589\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"5\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%6.\"/><w:lvlJc w:val=\"right\"/><w:pPr><w:ind w:left=\"4309\" w:hanging=\"180\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"6\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%7.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"5029\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"7\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%8.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"5749\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"8\"><w:start w:val=\"");
oNumberXml.WriteString(wsStart);
oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%9.\"/><w:lvlJc w:val=\"right\"/><w:pPr><w:ind w:left=\"6469\" w:hanging=\"180\"/></w:pPr></w:lvl></w:abstractNum>");
}
return true;
}
void TList<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return;
m_pInterpretator->CloseP();
}
TListElement<COOXMLInterpretator>::TListElement(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
bool TListElement<COOXMLInterpretator>::Open(const std::vector<NSCSS::CNode>& arSelectors)
{
return ValidInterpretator();
}
void TListElement<COOXMLInterpretator>::Close(const std::vector<NSCSS::CNode>& arSelectors)
{
if (!ValidInterpretator())
return;
m_pInterpretator->CloseP();
}
inline bool ElementInTable(const std::vector<NSCSS::CNode>& arSelectors)
{
return arSelectors.crend() != std::find_if(arSelectors.crbegin(), arSelectors.crend(), [](const NSCSS::CNode& oNode) { return L"table" == oNode.m_wsName; });
}
inline bool NotValidExtension(const std::wstring& sExtention)
{
return sExtention != L"bmp" && sExtention != L"emf" && sExtention != L"emz" && sExtention != L"eps" && sExtention != L"fpx" && sExtention != L"gif" &&
sExtention != L"jpe" && sExtention != L"jpeg" && sExtention != L"jpg" && sExtention != L"jfif" && sExtention != L"pct" && sExtention != L"pict" &&
@ -21,11 +819,13 @@ bool NotValidExtension(const std::wstring& sExtention)
sExtention != L"tga" && sExtention != L"tpic" && sExtention != L"tiff" && sExtention != L"tif" && sExtention != L"wmf" && !IsSVG(sExtention);
}
inline bool IsSVG(const std::wstring& wsExtention)
{
return L"svg" == wsExtention || L"svg+xml" == wsExtention;
}
bool ReadSVG(const std::wstring& wsSvg, NSFonts::IApplicationFonts* pFonts, const std::wstring& wsTempDir, const std::wstring& wsImagePath)
{
if (wsSvg.empty())
return false;
MetaFile::IMetaFile* pSvgReader = MetaFile::Create(pFonts);
if (!pSvgReader->LoadFromString(wsSvg))
{
@ -96,7 +896,6 @@ bool ReadSVG(const std::wstring& wsSvg, NSFonts::IApplicationFonts* pFonts, cons
pGrRenderer->put_Width(dWidth);
pGrRenderer->put_Height(dHeight);
// TODO: src directory as tmp - it's not good idea
pSvgReader->SetTempDirectory(wsTempDir);
pSvgReader->DrawOnRenderer(pGrRenderer, 0, 0, dWidth, dHeight);
@ -121,7 +920,7 @@ bool ReadBase64(const std::wstring& wsSrc, const std::wstring& wsImagePath, NSFo
size_t nEndBase = wsSrc.find(L";", nBase);
if (nEndBase == std::wstring::npos)
return false;
return bRes;
wsExtention = wsSrc.substr(nBase, nEndBase - nBase);
@ -129,11 +928,11 @@ bool ReadBase64(const std::wstring& wsSrc, const std::wstring& wsImagePath, NSFo
wsExtention = L"jpg";
if (NotValidExtension(wsExtention))
return false;
return bRes;
nBase = wsSrc.find(L"base64", nEndBase);
if (nBase == std::wstring::npos)
return false;
return bRes;
int nOffset = nBase + 7;
int nSrcLen = (int)(wsSrc.length() - nBase + 1);
@ -183,17 +982,7 @@ bool CanUseThisPath(const std::wstring& wsPath, const std::wstring& wsSrcPath, c
if (!wsCorePath.empty())
{
const std::wstring wsFullPath = NSSystemPath::ShortenPath(NSSystemPath::Combine(wsSrcPath, wsPath));
std::wstring::const_iterator itFirst{wsFullPath.cbegin()};
std::wstring::const_iterator itSecond{wsCorePath.cbegin()};
for (;itFirst != wsFullPath.cend() && itSecond != wsCorePath.cend(); ++itFirst, ++itSecond)
{
if (*itFirst != *itSecond)
return false;
}
return true;
return boost::starts_with(wsFullPath, wsCorePath);
}
if (wsPath.length() >= 3 && L"../" == wsPath.substr(0, 3))
@ -202,43 +991,6 @@ bool CanUseThisPath(const std::wstring& wsPath, const std::wstring& wsSrcPath, c
return true;
}
std::wstring NormalizePath(const std::wstring& wsPath)
{
return NSSystemPath::ShortenPath(wsPath);
}
std::wstring GetFileExtention(const std::wstring& wsFilePath)
{
return NSFile::GetFileExtention(wsFilePath);
}
std::wstring GetFileName(const std::wstring& wsFilePath)
{
return NSFile::GetFileName(wsFilePath);
}
bool DownloadImage(const std::wstring& wsHref, const std::wstring& wsDst)
{
NSNetwork::NSFileTransport::CFileDownloader oDownloadImg(wsHref, false);
oDownloadImg.SetFilePath(wsDst);
return oDownloadImg.DownloadSync();
}
bool ReadAllTextUtf8(const std::wstring& wsFilePath, std::wstring& wsText)
{
return NSFile::CFileBinary::ReadAllTextUtf8(wsFilePath, wsText);
}
bool RemoveFile(const std::wstring& wsFilePath)
{
return NSFile::CFileBinary::Remove(wsFilePath);
}
std::wstring CombinePaths(const std::wstring& wsFirstPath, const std::wstring& wsSecondPath)
{
return NSSystemPath::Combine(wsFirstPath, wsSecondPath);
}
bool CopyImage(std::wstring wsImageSrc, const std::wstring& wsSrc, const std::wstring& wsDst, bool bIsAllowExternalLocalFiles)
{
bool bRes = false;
@ -247,11 +999,11 @@ bool CopyImage(std::wstring wsImageSrc, const std::wstring& wsSrc, const std::ws
if (!bIsAllowExternalLocalFiles)
{
wsImageSrc = NSSystemPath::NormalizePath(wsImageSrc);
std::wstring wsStartSrc = NSSystemPath::NormalizePath(wsSrc);
const std::wstring wsStartSrc = NSSystemPath::NormalizePath(wsSrc);
bAllow = wsImageSrc.substr(0, wsStartSrc.length()) == wsStartSrc;
}
if (bAllow)
bRes = NSFile::CFileBinary::Copy(wsImageSrc, wsDst);
bRes = NSFile::CFileBinary::Copy(wsSrc, wsDst);
return bRes;
}
@ -303,5 +1055,4 @@ bool UpdateImageData(const std::wstring& wsImagePath, TImageData& oImageData)
return true;
}
}

View File

@ -5,145 +5,32 @@
#include "../Interpretators/OOXMLInterpretator.h"
#include <stack>
namespace XmlUtils { class CXmlLiteReader; }
namespace HTML
{
template<>
struct TAnchor<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TAnchor(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return false;
std::wstring wsRef, wsAlt, wsName;
bool bCross = false;
if (arSelectors.back().GetAttributeValue(L"href", wsRef) && wsRef.find('#') != std::wstring::npos)
bCross = true;
if (arSelectors.back().GetAttributeValue(L"name", wsName))
m_pInterpretator->WriteBookmark(wsName);
arSelectors.back().GetAttributeValue(L"alt", wsAlt);
if (!m_pInterpretator->OpenP())
m_pInterpretator->CloseR();
else
m_pInterpretator->WritePPr(arSelectors);
if (bCross)
m_pInterpretator->OpenCrossHyperlink(wsRef, arSelectors);
else
{
std::wstring wsTooltip(wsRef);
arSelectors.back().GetAttributeValue(L"title", wsTooltip);
m_pInterpretator->OpenExternalHyperlink(wsRef, wsTooltip, arSelectors);
}
return true;
}
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return;
bool bCross = false;
std::wstring wsFootnote;
if (arSelectors.back().m_wsStyle.find(L"mso-footnote-id") != std::wstring::npos)
wsFootnote = arSelectors.back().m_wsStyle.substr(arSelectors.back().m_wsStyle.rfind(L':') + 1);
else
{
if (arSelectors.back().GetAttributeValue(L"epub:type", wsFootnote) && wsFootnote.find(L"noteref"))
wsFootnote = L"href";
}
std::wstring wsRef;
if (arSelectors.back().GetAttributeValue(L"href", wsRef))
{
if(wsRef.find('#') != std::wstring::npos)
bCross = true;
}
if (bCross)
{
if (wsFootnote == L"href")
wsFootnote = wsRef.substr(wsRef.find('#') + 1);
m_pInterpretator->CloseCrossHyperlink(arSelectors, wsFootnote, wsRef);
}
else
m_pInterpretator->CloseExternalHyperlink();
}
TAnchor(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
template<>
struct TAbbr<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TAbbr(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return false;
std::wstring wsTitle;
if (!arSelectors.back().GetAttributeValue(L"title", wsTitle))
return false;
m_pInterpretator->WritePPr(arSelectors);
XmlString* pCurrentDocument{&m_pInterpretator->GetCurrentDocument()};
pCurrentDocument->WriteString(L"<w:r><w:fldChar w:fldCharType=\"begin\"/></w:r><w:r><w:instrText>HYPERLINK \\l \"" + m_pInterpretator->AddLiteBookmark() + L"\" \\o \"");
pCurrentDocument->WriteEncodeXmlString(wsTitle);
pCurrentDocument->WriteString(L"\"</w:instrText></w:r>");
pCurrentDocument->WriteString(L"<w:r><w:fldChar w:fldCharType=\"separate\"/></w:r>");
return true;
}
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return;
m_pInterpretator->GetCurrentDocument().WriteString(L"<w:r><w:fldChar w:fldCharType=\"end\"/></w:r>");
}
TAbbr(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
template<>
struct TBreak<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TBreak(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return false;
m_pInterpretator->Break(arSelectors);
return true;
}
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return;
}
TBreak(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
template<>
@ -151,291 +38,82 @@ struct TDivision<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
std::stack<UINT> m_arFootnoteIDs;
TDivision(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return false;
m_pInterpretator->UpdatePageStyle(arSelectors);
UINT unMsoFootnote = 0;
if (L"footnote" == arSelectors.back().GetAttributeValue(L"epub:type"))
++unMsoFootnote;
if (std::wstring::npos != arSelectors.back().m_wsStyle.find(L"mso-element:footnote"))
++unMsoFootnote;
std::wstring wsFootnoteID;
if (!arSelectors.back().m_wsId.empty())
{
wsFootnoteID = m_pInterpretator->FindFootnote(arSelectors.back().m_wsId);
if (!wsFootnoteID.empty())
++unMsoFootnote;
if (unMsoFootnote >= 2 && !wsFootnoteID.empty())
{
m_pInterpretator->OpenFootnote(wsFootnoteID);
m_pInterpretator->SetCurrentDocument(&m_pInterpretator->GetNotesXml());
}
}
m_arFootnoteIDs.push(unMsoFootnote);
return true;
}
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator() || m_arFootnoteIDs.empty())
return;
if (m_arFootnoteIDs.top() >= 2)
{
m_pInterpretator->CloseFootnote();
m_pInterpretator->RollBackState();
}
m_arFootnoteIDs.pop();
}
TDivision(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
bool NotValidExtension(const std::wstring& sExtention);
bool IsSVG(const std::wstring& wsExtention);
bool ReadSVG(const std::wstring& wsSvg, NSFonts::IApplicationFonts* pFonts, const std::wstring& wsTempDir, const std::wstring& wsImagePath);
bool ReadBase64(const std::wstring& wsSrc, const std::wstring& wsImagePath, NSFonts::IApplicationFonts* pFonts, const std::wstring& wsTempDir, std::wstring& wsExtention);
bool GetStatusUsingExternalLocalFiles();
bool CanUseThisPath(const std::wstring& wsPath, const std::wstring& wsSrcPath, const std::wstring& wsCorePath, bool bIsAllowExternalLocalFiles);
std::wstring NormalizePath(const std::wstring& wsPath);
std::wstring CombinePaths(const std::wstring& wsFirstPath, const std::wstring& wsSecondPath);
std::wstring GetFileExtention(const std::wstring& wsFilePath);
std::wstring GetFileName(const std::wstring& wsFilePath);
bool DownloadImage(const std::wstring& wsHref, const std::wstring& wsDst);
bool CopyImage(std::wstring wsImageSrc, const std::wstring& wsSrc, const std::wstring& wsDst, bool bIsAllowExternalLocalFiles);
bool UpdateImageData(const std::wstring& wsImagePath, TImageData& oImageData);
bool ReadAllTextUtf8(const std::wstring& wsFilePath, std::wstring& wsText);
bool RemoveFile(const std::wstring& wsFilePath);
template<>
struct TImage<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
std::vector<std::wstring> m_arrImages;
XmlUtils::CXmlLiteReader* m_pXmlReader; //TODO:: подумать как можно иначе получить текс в svg теге
TImage(COOXMLInterpretator* pInterpretator)
: TTag(pInterpretator)
{}
TImage(COOXMLInterpretator* pInterpretator, XmlUtils::CXmlLiteReader* pXmlReader);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return false;
template<>
struct TFont<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TFont(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
const std::wstring wsAlt{arSelectors.back().GetAttributeValue(L"alt")};
std::wstring wsSrc{arSelectors.back().GetAttributeValue(L"src")};
template<>
struct TInput<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TInput(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
TImageData oImageData;
template<>
struct TBaseFont<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TBaseFont(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
std::wstring wsTempValue;
NSCSS::NSProperties::CDigit oTempDigit;
template<>
struct TBlockquote<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
std::map<std::wstring, UINT> m_mDivs;
#define GET_UNIT_DATA(variable_data, data_variable)\
if (NSCSS::UnitMeasure::None == data_variable.GetUnitMeasure())\
variable_data = static_cast<UINT>(NSCSS::CUnitMeasureConverter::ConvertPx(data_variable.ToDouble(), NSCSS::Inch, 96) * 914400);\
else\
variable_data = static_cast<UINT>(data_variable.ToDouble(NSCSS::Inch) * 914400)
TBlockquote(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
#define READ_IMAGE_DATA(name_data, variable_data)\
if (arSelectors.back().GetAttributeValue(name_data, wsTempValue))\
{\
if (oTempDigit.SetValue(wsTempValue))\
{\
GET_UNIT_DATA(variable_data, oTempDigit);\
}\
}
template<>
struct THorizontalRule<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
UINT m_unShapeId;
READ_IMAGE_DATA(L"width", oImageData.m_unWidth);
READ_IMAGE_DATA(L"height", oImageData.m_unHeight);
READ_IMAGE_DATA(L"hspace", oImageData.m_nHSpace);
READ_IMAGE_DATA(L"vspace", oImageData.m_nVSpace);
THorizontalRule(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
if (nullptr != arSelectors.back().m_pCompiledStyle)
{
oTempDigit = arSelectors.back().m_pCompiledStyle->m_oDisplay.GetWidth();
template<>
struct TList<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
UINT m_unNumberingId;
if (0 == oImageData.m_unWidth && !oTempDigit.Empty())
{
GET_UNIT_DATA(oImageData.m_unWidth, oTempDigit);
}
TList(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
oTempDigit = arSelectors.back().m_pCompiledStyle->m_oDisplay.GetHeight();
if (0 == oImageData.m_unHeight && !oTempDigit.Empty())
{
GET_UNIT_DATA(oImageData.m_unHeight, oTempDigit);
}
}
if (wsSrc.empty())
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
bool bRes = false;
std::wstring wsExtention;
const std::wstring wsImagePath{m_pInterpretator->GetMediaDir() + L'i' + std::to_wstring(m_arrImages.size())};
// Предполагаем картинку в Base64
if (wsSrc.length() > 4 && wsSrc.substr(0, 4) == L"data" && wsSrc.find(L"/", 4) != std::wstring::npos)
bRes = ReadBase64(wsSrc, wsImagePath, m_pInterpretator->GetFonts(), m_pInterpretator->GetTempDir(), wsExtention);
const bool bIsAllowExternalLocalFiles = GetStatusUsingExternalLocalFiles();
if (!bRes && (wsSrc.length() <= 7 || L"http" != wsSrc.substr(0, 4)))
{
wsSrc = NormalizePath(wsSrc);
if (!CanUseThisPath(wsSrc, m_pInterpretator->GetSrcPath(), m_pInterpretator->GetCorePath(), bIsAllowExternalLocalFiles))
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
}
// Проверка расширения
if (!bRes)
{
wsExtention = GetFileExtention(wsSrc);
std::transform(wsExtention.begin(), wsExtention.end(), wsExtention.begin(), tolower);
std::wstring::const_iterator itFound = std::find_if(wsExtention.cbegin(), wsExtention.cend(), [](wchar_t wChar){ return !iswalpha(wChar) && L'+' != wChar; });
if (wsExtention.cend() != itFound)
wsExtention.erase(itFound, wsExtention.cend());
}
const std::wstring wsBasePath{m_pInterpretator->GetBasePath()};
// Предполагаем картинку в сети
if (!bRes &&
((!wsBasePath.empty() && wsBasePath.length() > 4 && wsBasePath.substr(0, 4) == L"http") ||
(wsSrc.length() > 4 && wsSrc.substr(0, 4) == L"http")))
{
const std::wstring wsDst = wsImagePath + L'.' + ((!wsExtention.empty()) ? wsExtention : L"png");
// Проверка gc_allowNetworkRequest предполагается в kernel_network
bRes = DownloadImage(m_pInterpretator->GetBasePath() + wsSrc, wsDst);
if (!bRes)
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
if (IsSVG(wsExtention))
{
std::wstring wsFileData;
if (!ReadAllTextUtf8(wsDst, wsFileData) ||
!ReadSVG(wsFileData, m_pInterpretator->GetFonts(), m_pInterpretator->GetTempDir(), wsImagePath))
bRes = false;
RemoveFile(wsDst);
wsExtention = L"png";
}
else if (wsExtention.empty())
{
//TODO:: лучше узнавать формат изображения из содержимого
wsExtention = L"png";
}
}
int nImageId = -1;
if (!bRes)
{
if (NotValidExtension(wsExtention))
{
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
return true;
}
// Проверка на повтор
std::vector<std::wstring>::iterator nFind = std::find(m_arrImages.begin(), m_arrImages.end(), wsSrc);
if (nFind != m_arrImages.end())
{
bRes = true;
nImageId = nFind - m_arrImages.begin();
}
}
// Предполагаем картинку по локальному пути
if (!bRes)
{
const std::wstring wsDst = wsImagePath + L'.' + wsExtention;
if (!m_pInterpretator->GetBasePath().empty())
{
if (!bRes)
bRes = CopyImage(CombinePaths(m_pInterpretator->GetBasePath(), wsSrc), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
if (!bRes)
bRes = CopyImage(CombinePaths(m_pInterpretator->GetSrcPath(), CombinePaths(m_pInterpretator->GetBasePath(), wsSrc)), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
}
if (!bRes)
bRes = CopyImage(CombinePaths(m_pInterpretator->GetSrcPath(), wsSrc), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
if (!bRes)
bRes = CopyImage(m_pInterpretator->GetSrcPath() + L"/" + GetFileName(wsSrc), m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
if (!bRes)
bRes = CopyImage(wsSrc, m_pInterpretator->GetSrcPath(), wsDst, bIsAllowExternalLocalFiles);
}
if (!bRes)
m_pInterpretator->WriteAlternativeImage(wsAlt, wsSrc, oImageData);
else
{
m_arrImages.push_back(wsSrc);
m_pInterpretator->WritePPr(arSelectors);
const std::wstring wsImageID{std::to_wstring(m_arrImages.size())};
if (nImageId < 0)
{
m_pInterpretator->WriteImageRels(wsImageID, wsImageID + L'.' + wsExtention);
m_arrImages.push_back(wsSrc);
}
if (!oImageData.ZeroSize())
{
m_pInterpretator->WriteImage(oImageData, wsImageID);
return true;
}
TImageData oNewImageData{oImageData};
if (!UpdateImageData(wsImagePath + L'.' + wsExtention, oNewImageData))
return false;
m_pInterpretator->WriteImage(oNewImageData, wsImageID);
}
return true;
}
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override
{
if (!ValidInterpretator())
return;
}
template<>
struct TListElement<COOXMLInterpretator> : public TTag<COOXMLInterpretator>
{
TListElement(COOXMLInterpretator* pInterpretator);
virtual bool Open(const std::vector<NSCSS::CNode>& arSelectors) override;
virtual void Close(const std::vector<NSCSS::CNode>& arSelectors) override;
};
}

View File

@ -5,9 +5,11 @@
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#include "../Common/3dParty/html/htmltoxhtml.h"
#include "htmlfile2.h"
#ifdef USE_OLD_HTML_CONVERTER
#include "../Common/3dParty/html/htmltoxhtml.h".
#include "../Common/3dParty/html/css/src/CCssCalculator.h"
#include "../Common/3dParty/html/css/src/xhtml/CDocumentStyle.h"
#include "../Common/Network/FileTransporter/include/FileTransporter.h"
@ -23,13 +25,10 @@
#include "../DesktopEditor/raster/BgraFrame.h"
#include "../DesktopEditor/graphics/pro/Graphics.h"
#include "htmlfile2.h"
#include "src/Languages.h"
#include <boost/regex.hpp>
#include "HTMLReader.h"
#ifndef VALUE2STR
#define VALUE_TO_STRING(x) #x
#define VALUE2STR(x) VALUE_TO_STRING(x)
@ -4082,71 +4081,7 @@ private:
if(m_oLightReader.IsEmptyNode())
return false;
CloseP(oXml, arSelectors);
CTextSettings oTSLi(oTS);
++oTSLi.nLi;
//Нумерованный список
if (L"ol" == arSelectors.back().m_wsName)
{
int nStart = 1;
while(m_oLightReader.MoveToNextAttribute())
if(m_oLightReader.GetName() == L"start")
nStart = NSStringFinder::ToInt(m_oLightReader.GetText(), 1);
m_oLightReader.MoveToElement();
oTSLi.bNumberingLi = true;
const std::wstring wsStart(std::to_wstring(nStart));
m_oNumberXml.WriteString(L"<w:abstractNum w:abstractNumId=\"");
m_oNumberXml.WriteString(std::to_wstring(m_nNumberingId++));
m_oNumberXml.WriteString(L"\"><w:multiLevelType w:val=\"hybridMultilevel\"/><w:lvl w:ilvl=\"0\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%1.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"709\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"1\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%2.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"1429\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"2\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%3.\"/><w:lvlJc w:val=\"right\"/><w:pPr><w:ind w:left=\"2149\" w:hanging=\"180\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"3\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%4.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"2869\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"4\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%5.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"3589\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"5\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%6.\"/><w:lvlJc w:val=\"right\"/><w:pPr><w:ind w:left=\"4309\" w:hanging=\"180\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"6\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%7.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"5029\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"7\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%8.\"/><w:lvlJc w:val=\"left\"/><w:pPr><w:ind w:left=\"5749\" w:hanging=\"360\"/></w:pPr></w:lvl><w:lvl w:ilvl=\"8\"><w:start w:val=\"");
m_oNumberXml.WriteString(wsStart);
m_oNumberXml.WriteString(L"\"/><w:numFmt w:val=\"decimal\"/><w:isLgl w:val=\"false\"/><w:suff w:val=\"tab\"/><w:lvlText w:val=\"%9.\"/><w:lvlJc w:val=\"right\"/><w:pPr><w:ind w:left=\"6469\" w:hanging=\"180\"/></w:pPr></w:lvl></w:abstractNum>");
}
else
oTSLi.bNumberingLi = false;
CTextSettings oTSList{oTSLi};
oTSList.oAdditionalStyle.m_oMargin.SetTop (100, NSCSS::UnitMeasure::Twips, 0, true);
oTSList.oAdditionalStyle.m_oMargin.SetBottom(100, NSCSS::UnitMeasure::Twips, 0, true);
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode2(nDeath))
{
const std::wstring wsName = m_oLightReader.GetName();
if (L"li" == wsName)
ReadListElement(oXml, arSelectors, oTSList);
else
{
CloseP(oXml, arSelectors);
readInside(oXml, arSelectors, oTSLi, wsName);
}
}
CloseP(oXml, arSelectors);
return true;
}
bool readLi (NSStringUtils::CStringBuilder* oXml, std::vector<NSCSS::CNode>& sSelectors, CTextSettings& oTS, bool bType)
@ -5069,51 +5004,65 @@ private:
return true;
}
};
#else
#include "HTMLReader.h"
#endif
CHtmlFile2::CHtmlFile2()
{
#ifdef USE_OLD_HTML_CONVERTER
m_internal = new CHtmlFile2_Private();
#endif
}
CHtmlFile2::~CHtmlFile2()
{
#ifdef USE_OLD_HTML_CONVERTER
RELEASEOBJECT(m_internal);
#endif
}
bool CHtmlFile2::IsHtmlFile(const std::wstring& sFile)
{
#ifdef USE_OLD_HTML_CONVERTER
// Конвертируем в xhtml
if(!m_internal->htmlXhtml(sFile))
return false;
// Читаем html
return m_internal->isHtml();
#endif
return true;
}
bool CHtmlFile2::IsMhtFile(const std::wstring& sFile)
{
#ifdef USE_OLD_HTML_CONVERTER
// Конвертируем в xhtml
if(!m_internal->mhtXhtml(sFile))
return false;
// Читаем html
return m_internal->isHtml();
#endif
return true;
}
void CHtmlFile2::SetTmpDirectory(const std::wstring& sFolder)
{
#ifdef USE_OLD_HTML_CONVERTER
m_internal->m_sTmp = NSSystemPath::NormalizePath(sFolder);
#endif
}
void CHtmlFile2::SetCoreDirectory(const std::wstring& wsFolder)
{
#ifdef USE_OLD_HTML_CONVERTER
m_internal->m_sCore = NSSystemPath::NormalizePath(wsFolder);
#endif
}
HRESULT CHtmlFile2::OpenHtml(const std::wstring& sSrc, const std::wstring& sDst, CHtmlParams* oParams)
{
HTML::CHTMLReader oHTMLReader;
return oHTMLReader.ConvertFromTo(sSrc, sDst);
#ifdef USE_OLD_HTML_CONVERTER
if(!m_internal->m_oLightReader.IsValid())
if(!IsHtmlFile(sSrc))
return S_FALSE;
@ -5132,10 +5081,15 @@ HRESULT CHtmlFile2::OpenHtml(const std::wstring& sSrc, const std::wstring& sDst,
m_internal->readSrc();
m_internal->write();
return S_OK;
#else
HTML::CHTMLReader oHTMLReader;
return oHTMLReader.ConvertFromTo(sSrc, sDst);
#endif
}
HRESULT CHtmlFile2::OpenMht(const std::wstring& sSrc, const std::wstring& sDst, CHtmlParams* oParams)
{
#ifdef USE_OLD_HTML_CONVERTER
if(!m_internal->m_oLightReader.IsValid())
if(!IsMhtFile(sSrc))
return S_FALSE;
@ -5154,10 +5108,14 @@ HRESULT CHtmlFile2::OpenMht(const std::wstring& sSrc, const std::wstring& sDst,
m_internal->readSrc();
m_internal->write();
return S_OK;
#else
return S_FALSE;
#endif
}
HRESULT CHtmlFile2::OpenBatchHtml(const std::vector<std::wstring>& sSrc, const std::wstring& sDst, CHtmlParams* oParams)
{
#ifdef USE_OLD_HTML_CONVERTER
m_internal->m_sDst = sDst;
m_internal->CreateDocxEmpty(oParams);
bool bFirst = true;
@ -5194,8 +5152,11 @@ HRESULT CHtmlFile2::OpenBatchHtml(const std::vector<std::wstring>& sSrc, const s
m_internal->write();
return S_OK;
#endif
return S_FALSE;
}
#ifdef USE_OLD_HTML_CONVERTER
std::wstring CTableRow::ConvertToOOXML(const CTable& oTable, int nInstruction)
{
if (m_arCells.empty())
@ -5351,3 +5312,4 @@ std::wstring CTableCell::ConvertToOOXML(const CTable& oTable, UINT unColumnNumbe
return oCell.GetData();
}
#endif

View File

@ -76,7 +76,9 @@ class CHtmlFile2_Private;
class HTMLFILE2_DECL_EXPORT CHtmlFile2
{
private:
#ifdef USE_OLD_HTML_CONVERTER
CHtmlFile2_Private* m_internal;
#endif
public:
CHtmlFile2();
~CHtmlFile2();