Merge pull request #1466 from ONLYOFFICE/fix/mht

Improved html and mht conversion
This commit is contained in:
Oleg Korshul
2024-04-19 20:50:11 +03:00
committed by GitHub
27 changed files with 2925 additions and 1825 deletions

View File

@ -12,22 +12,20 @@
#include "StaticFunctions.h"
#include "ConstValues.h"
#define DEFAULTFONTSIZE 28 // 14 * 2
#define DEFAULT_FONT_SIZE 28 // 14 * 2
namespace NSCSS
{
typedef std::map<std::wstring, std::wstring>::const_iterator styles_iterator;
CCompiledStyle::CCompiledStyle() : m_nDpi(96), m_UnitMeasure(Point)
{
m_oFont.SetSize(std::to_wstring(DEFAULTFONTSIZE), 0, true);
}
{}
CCompiledStyle::CCompiledStyle(const CCompiledStyle& oStyle) :
m_arParentsStyles(oStyle.m_arParentsStyles), m_sId(oStyle.m_sId),
m_nDpi(oStyle.m_nDpi), m_UnitMeasure(oStyle.m_UnitMeasure),
m_oFont(oStyle.m_oFont), m_oMargin(oStyle.m_oMargin), m_oPadding(oStyle.m_oPadding), m_oBackground(oStyle.m_oBackground),
m_oText(oStyle.m_oText), m_oBorder(oStyle.m_oBorder), m_oDisplay(oStyle.m_oDisplay){}
CCompiledStyle::CCompiledStyle(const CCompiledStyle& oStyle) :
m_arParentsStyles(oStyle.m_arParentsStyles), m_sId(oStyle.m_sId),
m_nDpi(oStyle.m_nDpi), m_UnitMeasure(oStyle.m_UnitMeasure),
m_oFont(oStyle.m_oFont), m_oMargin(oStyle.m_oMargin), m_oPadding(oStyle.m_oPadding), m_oBackground(oStyle.m_oBackground),
m_oText(oStyle.m_oText), m_oBorder(oStyle.m_oBorder), m_oDisplay(oStyle.m_oDisplay){}
CCompiledStyle::~CCompiledStyle()
{
@ -68,9 +66,7 @@ namespace NSCSS
bool CCompiledStyle::operator== (const CCompiledStyle& oStyle) const
{
return GetId()[0] == oStyle.GetId()[0] &&
m_arParentsStyles == oStyle.m_arParentsStyles &&
m_oBackground == oStyle.m_oBackground &&
return m_oBackground == oStyle.m_oBackground &&
m_oBorder == oStyle.m_oBorder &&
m_oFont == oStyle.m_oFont &&
m_oMargin == oStyle.m_oMargin &&
@ -100,16 +96,6 @@ namespace NSCSS
m_UnitMeasure = enUnitMeasure;
}
void CCompiledStyle::SetSizeSourceWindow(const CSizeWindow &oSizeWindow)
{
m_oSourceWindow = oSizeWindow;
}
void CCompiledStyle::SetSizeDeviceWindow(const CSizeWindow &oSizeWindow)
{
m_oDeviceWindow = oSizeWindow;
}
bool CCompiledStyle::Empty() const
{
return m_oBackground.Empty() && m_oBorder.Empty() && m_oFont.Empty() &&
@ -124,8 +110,8 @@ namespace NSCSS
void CCompiledStyle::AddStyle(const std::map<std::wstring, std::wstring>& mStyle, const unsigned int unLevel, const bool& bHardMode)
{
const bool bIsThereBorder = (m_oBorder.Empty()) ? false : true;
const double dFontSize = m_oFont.GetSize().ToDouble(NSCSS::Twips);
const double dFontSize = (!m_oFont.GetSize().Empty()) ? m_oFont.GetSize().ToDouble(NSCSS::Twips) : DEFAULT_FONT_SIZE;
for (std::pair<std::wstring, std::wstring> pPropertie : mStyle)
{
std::transform(pPropertie.first.begin(), pPropertie.first.end(), pPropertie.first.begin(), tolower);
@ -183,45 +169,49 @@ namespace NSCSS
if (bIsThereBorder)
break;
m_oMargin.AddValue(pPropertie.second, unLevel, bHardMode);
m_oMargin.SetValues(pPropertie.second, unLevel, bHardMode);
m_oMargin.UpdateAll(dFontSize);
break;
}
CASE(L"margin-top"):
CASE(L"topmargin"):
{
if (bIsThereBorder)
break;
m_oMargin.AddTop(pPropertie.second, unLevel, bHardMode);
m_oMargin.SetTop(pPropertie.second, unLevel, bHardMode);
m_oMargin.UpdateTop(dFontSize);
break;
}
CASE(L"margin-right"):
CASE(L"margin-block-end"):
CASE(L"rightmargin"):
{
if (bIsThereBorder)
break;
m_oMargin.AddRight(pPropertie.second, unLevel, bHardMode);
m_oMargin.SetRight(pPropertie.second, unLevel, bHardMode);
m_oMargin.UpdateRight(dFontSize);
break;
}
CASE(L"margin-bottom"):
CASE(L"bottommargin"):
{
if (bIsThereBorder)
break;
m_oMargin.AddBottom(pPropertie.second, unLevel, bHardMode);
m_oMargin.SetBottom(pPropertie.second, unLevel, bHardMode);
m_oMargin.UpdateBottom(dFontSize);
break;
}
CASE(L"margin-left"):
CASE(L"margin-block-start"):
CASE(L"leftmargin"):
{
if (bIsThereBorder)
break;
m_oMargin.AddLeft(pPropertie.second, unLevel, bHardMode);
m_oMargin.SetLeft(pPropertie.second, unLevel, bHardMode);
m_oMargin.UpdateLeft(dFontSize);
break;
}
@ -229,35 +219,35 @@ namespace NSCSS
CASE(L"padding"):
CASE(L"mso-padding-alt"):
{
m_oPadding.AddValue(pPropertie.second, unLevel, bHardMode);
m_oPadding.SetValues(pPropertie.second, unLevel, bHardMode);
m_oPadding.UpdateAll(dFontSize);
break;
}
CASE(L"padding-top"):
CASE(L"mso-padding-top-alt"):
{
m_oPadding.AddTop(pPropertie.second, unLevel, bHardMode);
m_oPadding.SetTop(pPropertie.second, unLevel, bHardMode);
m_oPadding.UpdateTop(dFontSize);
break;
}
CASE(L"padding-right"):
CASE(L"mso-padding-right-alt"):
{
m_oPadding.AddRight(pPropertie.second, unLevel, bHardMode);
m_oPadding.SetRight(pPropertie.second, unLevel, bHardMode);
m_oPadding.UpdateRight(dFontSize);
break;
}
CASE(L"padding-bottom"):
CASE(L"mso-padding-bottom-alt"):
{
m_oPadding.AddBottom(pPropertie.second, unLevel, bHardMode);
m_oPadding.SetBottom(pPropertie.second, unLevel, bHardMode);
m_oPadding.UpdateBottom(dFontSize);
break;
}
CASE(L"padding-left"):
CASE(L"mso-padding-left-alt"):
{
m_oPadding.AddLeft(pPropertie.second, unLevel, bHardMode);
m_oPadding.SetLeft(pPropertie.second, unLevel, bHardMode);
m_oPadding.UpdateLeft(dFontSize);
break;
}
@ -305,6 +295,11 @@ namespace NSCSS
m_oBorder.SetColor(pPropertie.second, unLevel, bHardMode);
break;
}
CASE(L"border-collapse"):
{
m_oBorder.SetCollapse(pPropertie.second, unLevel, bHardMode);
break;
}
//BORDER TOP
CASE(L"border-top"):
{
@ -393,20 +388,12 @@ namespace NSCSS
CASE(L"background-color"):
{
m_oBackground.SetColor(pPropertie.second, unLevel, bHardMode);
if (bIsThereBorder)
m_oBackground.InBorder();
break;
}
CASE(L"background"):
CASE(L"bgcolor"):
{
m_oBackground.SetBackground(pPropertie.second, unLevel, bHardMode);
if (bIsThereBorder)
m_oBackground.InBorder();
break;
}
//DISPLAY
@ -431,6 +418,7 @@ namespace NSCSS
break;
}
CASE(L"vertical-align"):
CASE(L"valign"):
{
m_oDisplay.SetVAlign(pPropertie.second, unLevel, bHardMode);
break;
@ -510,4 +498,9 @@ namespace NSCSS
{
return m_sId;
}
bool CCompiledStyle::HaveThisParent(const std::wstring &wsParentName) const
{
return m_arParentsStyles.end() != m_arParentsStyles.find(wsParentName);
}
}

View File

@ -22,9 +22,6 @@ namespace NSCSS
unsigned short int m_nDpi;
UnitMeasure m_UnitMeasure;
CSizeWindow m_oSourceWindow;
CSizeWindow m_oDeviceWindow;
public:
NSProperties::CFont m_oFont;
NSProperties::CIndent m_oMargin;
@ -41,8 +38,6 @@ namespace NSCSS
void SetDpi(const unsigned short& uiDpi);
void SetUnitMeasure(const UnitMeasure& enUnitMeasure);
void SetSizeSourceWindow(const CSizeWindow& oSizeWindow);
void SetSizeDeviceWindow(const CSizeWindow& oSizeWindow);
bool Empty() const;
@ -57,6 +52,8 @@ namespace NSCSS
void SetID(const std::wstring& sId);
std::wstring GetId() const;
bool HaveThisParent(const std::wstring& wsParentName) const;
CCompiledStyle& operator+= (const CCompiledStyle& oElement);
CCompiledStyle& operator= (const CCompiledStyle& oElement);
bool operator== (const CCompiledStyle& oElement) const;

View File

@ -1,7 +1,6 @@
#include "CCssCalculator.h"
#include "CCssCalculator_Private.h"
namespace NSCSS
{
CCssCalculator::CCssCalculator()
@ -24,6 +23,11 @@ namespace NSCSS
return m_pInternal->GetCompiledStyle(oStyle, arSelectors, bIsSettings, unitMeasure);
}
bool CCssCalculator::CalculatePageStyle(NSProperties::CPage& oPageData, const std::vector<CNode> &arSelectors)
{
return m_pInternal->CalculatePageStyle(oPageData, arSelectors);
}
void CCssCalculator::AddStyles(const std::string &sStyle)
{
m_pInternal->AddStyles(sStyle);
@ -54,26 +58,6 @@ namespace NSCSS
m_pInternal->SetBodyTree(oTree);
}
void CCssCalculator::SetSizeSourceWindow(const CSizeWindow &oSizeWindow)
{
m_pInternal->SetSizeSourceWindow(oSizeWindow);
}
void CCssCalculator::SetSizeDeviceWindow(const CSizeWindow &oSizeWindow)
{
m_pInternal->SetSizeDeviceWindow(oSizeWindow);
}
CSizeWindow CCssCalculator::GetSizeSourceWindow() const
{
return m_pInternal->GetSizeSourceWindow();
}
CSizeWindow CCssCalculator::GetSizeDeviceWindow() const
{
return m_pInternal->GetSizeDeviceWindow();
}
UnitMeasure CCssCalculator::GetUnitMeasure() const
{
return m_pInternal->GetUnitMeasure();

View File

@ -22,6 +22,8 @@ namespace NSCSS
CCompiledStyle GetCompiledStyle(const std::vector<CNode> &arSelectors, const bool& bIsSettings = false, const UnitMeasure& unitMeasure = Point) const;
bool GetCompiledStyle(CCompiledStyle& oStyle, const std::vector<CNode> &arSelectors, const bool& bIsSettings = false, const UnitMeasure& unitMeasure = Point) const;
bool CalculatePageStyle(NSProperties::CPage& oPageData, const std::vector<CNode> &arSelectors);
// void AddStyle(const std::vector<std::string>& sSelectors, const std::string& sStyle);
void AddStyles (const std::string& sStyle);
void AddStyles (const std::wstring& wsStyle);
@ -31,12 +33,6 @@ namespace NSCSS
void SetDpi(const unsigned short int& nValue);
void SetBodyTree(const CTree &oTree);
void SetSizeSourceWindow(const CSizeWindow& oSizeWindow);
void SetSizeDeviceWindow(const CSizeWindow& oSizeWindow);
CSizeWindow GetSizeSourceWindow() const;
CSizeWindow GetSizeDeviceWindow() const;
UnitMeasure GetUnitMeasure() const;
std::wstring GetEncoding() const;
unsigned short int GetDpi() const;

View File

@ -86,6 +86,176 @@ namespace NSCSS
}
#ifdef CSS_CALCULATOR_WITH_XHTML
std::map<std::wstring, std::wstring> CCssCalculator_Private::GetPageData(const std::wstring &wsPageName)
{
if (m_arPageDatas.empty())
return {};
for (const TPageData& oPageData : m_arPageDatas)
{
if (std::find(oPageData.m_wsNames.begin(), oPageData.m_wsNames.end(), wsPageName) != oPageData.m_wsNames.end())
return oPageData.m_mData;
}
return {};
}
void CCssCalculator_Private::SetPageData(NSProperties::CPage &oPage, const std::map<std::wstring, std::wstring> &mData, unsigned int unLevel, bool bHardMode)
{
for (const std::pair<std::wstring, std::wstring> &oData : mData)
{
if (L"margin" == oData.first)
oPage.SetMargin(oData.second, unLevel, bHardMode);
else if (L"size" == oData.first)
oPage.SetSize(oData.second, unLevel, bHardMode);
else if (L"mso-header-margin" == oData.first)
oPage.SetHeader(oData.second, unLevel, bHardMode);
else if (L"mso-footer-margin" == oData.first)
oPage.SetFooter(oData.second, unLevel, bHardMode);
}
}
std::vector<std::wstring> CCssCalculator_Private::CalculateAllNodes(const std::vector<CNode> &arSelectors)
{
std::vector<std::wstring> arNodes;
for (std::vector<CNode>::const_reverse_iterator oNode = arSelectors.rbegin(); oNode != arSelectors.rend(); ++oNode)
{
if (!oNode->m_wsName.empty())
arNodes.push_back(oNode->m_wsName);
if (!oNode->m_wsClass.empty())
{
if (oNode->m_wsClass.find(L' ') != std::wstring::npos)
{
std::vector<std::wstring> arClasses = NS_STATIC_FUNCTIONS::GetWordsW(oNode->m_wsClass, false, L" ");
arNodes.push_back(std::accumulate(arClasses.begin(), arClasses.end(), std::wstring(),
[](std::wstring sRes, const std::wstring& sClass)
{return sRes += L'.' + sClass + L' ';}));
}
else
arNodes.push_back(L'.' + oNode->m_wsClass);
}
if (!oNode->m_wsId.empty())
arNodes.push_back(L'#' + oNode->m_wsId);
}
return arNodes;
}
void CCssCalculator_Private::FindPrevAndKindElements(const CElement *pElement, const std::vector<std::wstring> &arNextNodes, std::vector<CElement*>& arFindedElements, const std::wstring &wsName, const std::vector<std::wstring> &arClasses)
{
if (arNextNodes.empty())
return;
const std::vector<CElement*> arTempPrev = pElement->GetPrevElements(arNextNodes.crbegin() + 1, arNextNodes.crend());
const std::vector<CElement*> arTempKins = pElement->GetNextOfKin(wsName, arClasses);
if (!arTempPrev.empty())
arFindedElements.insert(arFindedElements.end(), arTempPrev.begin(), arTempPrev.end());
if (!arTempKins.empty())
arFindedElements.insert(arFindedElements.end(), arTempKins.begin(), arTempKins.end());
}
std::vector<CElement*> CCssCalculator_Private::FindElements(std::vector<std::wstring> &arNodes, std::vector<std::wstring> &arNextNodes, bool bIsSettings)
{
std::vector<CElement*> arFindedElements;
std::wstring wsName, wsId;
std::vector<std::wstring> arClasses;
if (arNodes.back()[0] == L'#')
{
wsId = arNodes.back();
arNodes.pop_back();
arNextNodes.push_back(wsId);
}
if (arNodes.back()[0] == L'.')
{
arClasses = NS_STATIC_FUNCTIONS::GetWordsW(arNodes.back(), false, L" ");
arNextNodes.push_back(arNodes.back());
arNodes.pop_back();
}
wsName = arNodes.back();
arNodes.pop_back();
arNextNodes.push_back(wsName);
const std::map<std::wstring, CElement*>::const_iterator oFindName = m_mData.find(wsName);
std::map<std::wstring, CElement*>::const_iterator oFindId;
if (!wsId.empty())
{
oFindId = m_mData.find(wsId);
if (oFindId != m_mData.end() && NULL != m_mStatictics)
{
std::map<StatistickElement, unsigned int>::const_iterator oFindCountId = m_mStatictics->find(StatistickElement{StatistickElement::IsId, wsId});
if ((m_mStatictics->end() != oFindCountId) &&
(((bIsSettings && oFindCountId->second < MaxNumberRepetitions) ||
(!bIsSettings && oFindCountId->second >= MaxNumberRepetitions))))
{
if (!oFindId->second->Empty())
arFindedElements.push_back(oFindId->second);
}
FindPrevAndKindElements(oFindId->second, arNextNodes, arFindedElements, wsName);
}
}
if (!arClasses.empty())
{
if (!bIsSettings)
{
for (std::vector<std::wstring>::const_reverse_iterator iClass = arClasses.rbegin(); iClass != arClasses.rend(); ++iClass)
{
const std::map<std::wstring, CElement*>::const_iterator oFindClass = m_mData.find(*iClass);
if (oFindClass != m_mData.end())
{
if (!oFindClass->second->Empty())
arFindedElements.push_back(oFindClass->second);
FindPrevAndKindElements(oFindClass->second, arNextNodes, arFindedElements, wsName);
}
}
}
}
if (oFindName != m_mData.end())
{
if (!bIsSettings)
{
if (!oFindName->second->Empty())
arFindedElements.push_back(oFindName->second);
FindPrevAndKindElements(oFindName->second, arNextNodes, arFindedElements, wsName, arClasses);
}
}
if (arFindedElements.size() > 1)
{
std::sort(arFindedElements.rbegin(), arFindedElements.rend(),
[](CElement* oFirstElement, CElement* oSecondElement)
{
return oFirstElement->GetWeight() > oSecondElement->GetWeight();
});
}
return arFindedElements;
}
#endif
void CCssCalculator_Private::AddPageData(const std::wstring &wsPageNames, const std::wstring &wsStyles)
{
m_arPageDatas.push_back({NS_STATIC_FUNCTIONS::GetWordsW(wsPageNames), NS_STATIC_FUNCTIONS::GetRules(wsStyles)});
}
inline void CCssCalculator_Private::GetStylesheet(const KatanaStylesheet *oStylesheet)
{
for (size_t i = 0; i < oStylesheet->imports.length; ++i)
@ -308,231 +478,11 @@ namespace NSCSS
if (arSelectors.empty())
return CCompiledStyle();
SetUnitMeasure(unitMeasure);
CCompiledStyle oStyle;
if (!bIsSettings)
{
const std::map<std::vector<CNode>, CCompiledStyle*>::iterator oItem = m_mUsedStyles.find(arSelectors);
GetCompiledStyle(oStyle, arSelectors, bIsSettings, unitMeasure);
if (oItem != m_mUsedStyles.end())
return *oItem->second;
}
else if (NULL == m_mStatictics || m_mStatictics->empty())
{
CCompiledStyle oStyle;
oStyle.SetDpi(m_nDpi);
oStyle.SetUnitMeasure(m_UnitMeasure);
oStyle.SetID(arSelectors.back().m_wsName + ((!arSelectors.back().m_wsClass.empty()) ? L'.' + arSelectors.back().m_wsClass : L"") + ((arSelectors.back().m_wsId.empty()) ? L"" : L'#' + arSelectors.back().m_wsId) + L'-' + std::to_wstring(++m_nCountNodes));
oStyle.SetSizeDeviceWindow(m_oDeviceWindow);
oStyle.SetSizeSourceWindow(m_oSourceWindow);
return oStyle;
}
CCompiledStyle *pStyle = new CCompiledStyle();
pStyle->SetDpi(m_nDpi);
pStyle->SetUnitMeasure(m_UnitMeasure);
pStyle->SetSizeDeviceWindow(m_oDeviceWindow);
pStyle->SetSizeSourceWindow(m_oSourceWindow);
std::vector<std::wstring> arWords;
arWords.reserve(arSelectors.size() * 2);
std::vector<std::wstring> arNextNodes;
arNextNodes.reserve(arSelectors.size() * 2);
for (std::vector<CNode>::const_reverse_iterator oNode = arSelectors.rbegin(); oNode != arSelectors.rend(); ++oNode)
{
arWords.push_back(oNode->m_wsName);
//TODO:: проверить данный момент
// if (oNode->m_sName == L"td")
// pStyle->m_oMargin.SetPermission(false);
if (oNode->m_wsName == L"table")
pStyle->m_oBorder.Block();
if (!oNode->m_wsClass.empty())
{
if (oNode->m_wsClass.find(L' ') != std::wstring::npos)
{
std::vector<std::wstring> arClasses = NS_STATIC_FUNCTIONS::GetWordsW(oNode->m_wsClass, false, L" ");
if (arClasses.size() > 1)
arClasses.resize(unique(arClasses.begin(),arClasses.end()) - arClasses.begin());
switch (arClasses.size())
{
case 1:
{
arWords.push_back(L'.' + arClasses[0]);
break;
}
case 2:
{
arWords.push_back(L'.' + arClasses[0] + L" ." + arClasses[1]);
break;
}
case 3:
{
arWords.push_back(L'.' + arClasses[0] + L" ." + arClasses[1] + L" ." + arClasses[2]);
break;
}
default:
{
arWords.push_back(std::accumulate(arClasses.begin(), arClasses.end(), std::wstring(),
[](std::wstring sRes, const std::wstring& sClass)
{return sRes += L'.' + sClass + L' ';}));
break;
}
}
}
else
arWords.push_back(L'.' + oNode->m_wsClass);
}
if (!oNode->m_wsId.empty())
arWords.push_back(L'#' + oNode->m_wsId);
}
std::vector<CElement*> arElements;
for (size_t i = 0; i < arSelectors.size(); ++i)
{
std::wstring sName, sId;
std::vector<std::wstring> arClasses;
if (arWords.back()[0] == L'#')
{
sId = arWords.back();
arWords.pop_back();
arNextNodes.push_back(sId);
}
if (arWords.back()[0] == L'.')
{
arClasses = NS_STATIC_FUNCTIONS::GetWordsW(arWords.back(), false, L" ");
arNextNodes.push_back(arWords.back());
arWords.pop_back();
}
sName = arWords.back();
arWords.pop_back();
arNextNodes.push_back(sName);
pStyle->AddParent(sName);
const std::map<std::wstring, CElement*>::const_iterator oFindName = m_mData.find(sName);
std::map<std::wstring, CElement*>::const_iterator oFindId;
std::vector<CElement*> arFindElements;
if (!sId.empty())
{
oFindId = m_mData.find(sId);
if (oFindId != m_mData.end() && NULL != m_mStatictics)
{
std::map<StatistickElement, unsigned int>::const_iterator oFindCountId = m_mStatictics->find(StatistickElement{StatistickElement::IsId, sId});
if ((m_mStatictics->end() != oFindCountId) &&
(((bIsSettings && oFindCountId->second < MaxNumberRepetitions) ||
(!bIsSettings && oFindCountId->second >= MaxNumberRepetitions))))
{
if (!oFindId->second->Empty())
arFindElements.push_back(oFindId->second);
}
const std::vector<CElement*> arTempPrev = oFindId->second->GetPrevElements(arNextNodes.rbegin() + ((arClasses.empty()) ? 1 : 2), arNextNodes.rend());
if (!arTempPrev.empty())
arFindElements.insert(arFindElements.end(), arTempPrev.begin(), arTempPrev.end());
}
}
if (!arClasses.empty())
{
if (!bIsSettings)
{
for (std::vector<std::wstring>::const_reverse_iterator iClass = arClasses.rbegin(); iClass != arClasses.rend(); ++iClass)
{
const std::map<std::wstring, CElement*>::const_iterator oFindClass = m_mData.find(*iClass);
if (oFindClass != m_mData.end())
{
if (!oFindClass->second->Empty())
arFindElements.push_back(oFindClass->second);
const std::vector<CElement*> arTempPrev = oFindClass->second->GetPrevElements(arNextNodes.rbegin() + 2, arNextNodes.rend());
const std::vector<CElement*> arTempKins = oFindClass->second->GetNextOfKin(sName);
if (!arTempPrev.empty())
arFindElements.insert(arFindElements.end(), arTempPrev.begin(), arTempPrev.end());
if (!arTempKins.empty())
arFindElements.insert(arFindElements.end(), arTempKins.begin(), arTempKins.end());
}
}
}
}
if (oFindName != m_mData.end())
{
if (!bIsSettings)
{
if (!oFindName->second->Empty())
arFindElements.push_back(oFindName->second);
const std::vector<CElement*> arTempPrev = oFindName->second->GetPrevElements(arNextNodes.rbegin() + 1, arNextNodes.rend());
const std::vector<CElement*> arTempKins = oFindName->second->GetNextOfKin(sName, arClasses);
if (!arTempPrev.empty())
arFindElements.insert(arFindElements.end(), arTempPrev.begin(), arTempPrev.end());
if (!arTempKins.empty())
arFindElements.insert(arFindElements.end(), arTempKins.begin(), arTempKins.end());
}
}
if (arFindElements.size() > 1)
{
std::sort(arFindElements.rbegin(), arFindElements.rend(),
[](CElement* oFirstElement, CElement* oSecondElement)
{
return oFirstElement->GetWeight() > oSecondElement->GetWeight();
});
}
pStyle->AddStyle(arSelectors[i].m_mAttributes, i + 1);
for (const CElement* oElement : arFindElements)
pStyle->AddStyle(oElement->GetStyle(), i + 1);
if (NULL != m_mStatictics)
{
std::map<StatistickElement, unsigned int>::const_iterator oFindCountStyle = m_mStatictics->find(StatistickElement{StatistickElement::IsStyle, arSelectors[i].m_wsStyle});
if (oFindCountStyle != m_mStatictics->end())
{
if ((bIsSettings && oFindCountStyle->second < MaxNumberRepetitions) ||
(!bIsSettings && oFindCountStyle->second >= MaxNumberRepetitions))
pStyle->AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
else if (!bIsSettings)
pStyle->AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
}
else if (bIsSettings)
pStyle->AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
}
else
pStyle->AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
}
if (!bIsSettings)
{
pStyle->SetID(arSelectors.back().m_wsName + ((!arSelectors.back().m_wsClass.empty()) ? L'.' + arSelectors.back().m_wsClass : L"") + ((arSelectors.back().m_wsId.empty()) ? L"" : L'#' + arSelectors.back().m_wsId) + L'-' + std::to_wstring(++m_nCountNodes));
m_mUsedStyles[arSelectors] = pStyle;
}
return *pStyle;
return oStyle;
}
bool CCssCalculator_Private::GetCompiledStyle(CCompiledStyle &oStyle, const std::vector<CNode> &arSelectors, const bool &bIsSettings, const UnitMeasure &unitMeasure)
@ -558,180 +508,35 @@ namespace NSCSS
oStyle.SetUnitMeasure(m_UnitMeasure);
oStyle.SetID(arSelectors.back().m_wsName + ((!arSelectors.back().m_wsClass.empty()) ? L'.' + arSelectors.back().m_wsClass : L"") + ((arSelectors.back().m_wsId.empty()) ? L"" : L'#' + arSelectors.back().m_wsId) + L'-' + std::to_wstring(++m_nCountNodes));
oStyle.SetSizeDeviceWindow(m_oDeviceWindow);
oStyle.SetSizeSourceWindow(m_oSourceWindow);
return false;
}
oStyle.SetDpi(m_nDpi);
oStyle.SetUnitMeasure(m_UnitMeasure);
oStyle.SetSizeDeviceWindow(m_oDeviceWindow);
oStyle.SetSizeSourceWindow(m_oSourceWindow);
std::vector<std::wstring> arWords;
arWords.reserve(arSelectors.size() * 2);
std::vector<std::wstring> arNextNodes;
arNextNodes.reserve(arSelectors.size() * 2);
for (std::vector<CNode>::const_reverse_iterator oNode = arSelectors.rbegin(); oNode != arSelectors.rend(); ++oNode)
{
arWords.push_back(oNode->m_wsName);
// if (oNode->m_sName == L"td")
// oStyle.m_pMargin.SetPermission(false);
if (oNode->m_wsName == L"table")
oStyle.m_oBorder.Block();
if (!oNode->m_wsClass.empty())
{
if (oNode->m_wsClass.find(L' ') != std::wstring::npos)
{
std::vector<std::wstring> arClasses = NS_STATIC_FUNCTIONS::GetWordsW(oNode->m_wsClass, false, L" ");
if (arClasses.size() > 1)
arClasses.resize(unique(arClasses.begin(),arClasses.end()) - arClasses.begin());
switch (arClasses.size())
{
case 1:
{
arWords.push_back(L'.' + arClasses[0]);
break;
}
case 2:
{
arWords.push_back(L'.' + arClasses[0] + L" ." + arClasses[1]);
break;
}
case 3:
{
arWords.push_back(L'.' + arClasses[0] + L" ." + arClasses[1] + L" ." + arClasses[2]);
break;
}
default:
{
arWords.push_back(std::accumulate(arClasses.begin(), arClasses.end(), std::wstring(),
[](std::wstring sRes, const std::wstring& sClass)
{return sRes += L'.' + sClass + L' ';}));
break;
}
}
}
else
arWords.push_back(L'.' + oNode->m_wsClass);
}
if (!oNode->m_wsId.empty())
arWords.push_back(L'#' + oNode->m_wsId);
}
std::vector<CElement*> arElements;
std::vector<std::wstring> arNodes = CalculateAllNodes(arSelectors);
std::vector<std::wstring> arPrevNodes;
for (size_t i = 0; i < arSelectors.size(); ++i)
{
std::wstring sName, sId;
std::vector<std::wstring> arClasses;
oStyle.AddParent(arSelectors[i].m_wsName);
if (arWords.back()[0] == L'#')
// Скидываем некоторые внешние стили, которые внутри таблицы переопределяются
if (L"table" == arSelectors[i].m_wsName)
{
sId = arWords.back();
arWords.pop_back();
arNextNodes.push_back(sId);
oStyle.m_oFont.GetLineHeight().Clear();
oStyle.m_oPadding.Clear();
oStyle.m_oMargin.Clear();
}
if (arWords.back()[0] == L'.')
{
arClasses = NS_STATIC_FUNCTIONS::GetWordsW(arWords.back(), false, L" ");
arNextNodes.push_back(arWords.back());
arWords.pop_back();
}
oStyle.m_oBorder.Clear();
sName = arWords.back();
arWords.pop_back();
arNextNodes.push_back(sName);
oStyle.AddParent(sName);
CCompiledStyle oTempStyle;
const std::map<std::wstring, CElement*>::const_iterator oFindName = m_mData.find(sName);
std::map<std::wstring, CElement*>::const_iterator oFindId;
std::vector<CElement*> arFindElements;
oTempStyle.AddStyle(arSelectors[i].m_mAttributes, i + 1);
if (!sId.empty())
{
oFindId = m_mData.find(sId);
if (oFindId != m_mData.end() && NULL != m_mStatictics)
{
std::map<StatistickElement, unsigned int>::const_iterator oFindCountId = m_mStatictics->find(StatistickElement{StatistickElement::IsId, sId});
if ((m_mStatictics->end() != oFindCountId) &&
(((bIsSettings && oFindCountId->second < MaxNumberRepetitions) ||
(!bIsSettings && oFindCountId->second >= MaxNumberRepetitions))))
{
if (!oFindId->second->Empty())
arFindElements.push_back(oFindId->second);
}
const std::vector<CElement*> arTempPrev = oFindId->second->GetPrevElements(arNextNodes.rbegin() + ((arClasses.empty()) ? 1 : 2), arNextNodes.rend());
if (!arTempPrev.empty())
arFindElements.insert(arFindElements.end(), arTempPrev.begin(), arTempPrev.end());
}
}
if (!arClasses.empty())
{
if (!bIsSettings)
{
for (std::vector<std::wstring>::const_reverse_iterator iClass = arClasses.rbegin(); iClass != arClasses.rend(); ++iClass)
{
const std::map<std::wstring, CElement*>::const_iterator oFindClass = m_mData.find(*iClass);
if (oFindClass != m_mData.end())
{
if (!oFindClass->second->Empty())
arFindElements.push_back(oFindClass->second);
const std::vector<CElement*> arTempPrev = oFindClass->second->GetPrevElements(arNextNodes.rbegin() + 2, arNextNodes.rend());
const std::vector<CElement*> arTempKins = oFindClass->second->GetNextOfKin(sName);
if (!arTempPrev.empty())
arFindElements.insert(arFindElements.end(), arTempPrev.begin(), arTempPrev.end());
if (!arTempKins.empty())
arFindElements.insert(arFindElements.end(), arTempKins.begin(), arTempKins.end());
}
}
}
}
if (oFindName != m_mData.end())
{
if (!bIsSettings)
{
if (!oFindName->second->Empty())
arFindElements.push_back(oFindName->second);
const std::vector<CElement*> arTempPrev = oFindName->second->GetPrevElements(arNextNodes.rbegin() + 1, arNextNodes.rend());
const std::vector<CElement*> arTempKins = oFindName->second->GetNextOfKin(sName, arClasses);
if (!arTempPrev.empty())
arFindElements.insert(arFindElements.end(), arTempPrev.begin(), arTempPrev.end());
if (!arTempKins.empty())
arFindElements.insert(arFindElements.end(), arTempKins.begin(), arTempKins.end());
}
}
if (arFindElements.size() > 1)
{
std::sort(arFindElements.rbegin(), arFindElements.rend(),
[](CElement* oFirstElement, CElement* oSecondElement)
{
return oFirstElement->GetWeight() > oSecondElement->GetWeight();
});
}
for (const CElement* oElement : FindElements(arNodes, arPrevNodes, bIsSettings))
oTempStyle.AddStyle(oElement->GetStyle(), i + 1);
if (NULL != m_mStatictics)
{
@ -741,20 +546,17 @@ namespace NSCSS
{
if ((bIsSettings && oFindCountStyle->second < MaxNumberRepetitions) ||
(!bIsSettings && oFindCountStyle->second >= MaxNumberRepetitions))
oStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
oTempStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
else if (!bIsSettings)
oStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
oTempStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
}
else if (bIsSettings)
oStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
else /*if (bIsSettings)*/
oTempStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
}
else
oStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
oTempStyle.AddStyle(arSelectors[i].m_wsStyle, i + 1, true);
for (const CElement* oElement : arFindElements)
oStyle.AddStyle(oElement->GetStyle(), i + 1);
oStyle.AddStyle(arSelectors[i].m_mAttributes, i + 1);
oStyle += oTempStyle;
}
if (!bIsSettings)
@ -768,6 +570,37 @@ namespace NSCSS
return true;
}
bool CCssCalculator_Private::CalculatePageStyle(NSProperties::CPage &oPageData, const std::vector<CNode> &arSelectors)
{
if (arSelectors.empty())
return false;
std::vector<std::wstring> arNodes = CalculateAllNodes(arSelectors);
std::vector<std::wstring> arNextNodes;
for (size_t i = 0; i < arSelectors.size(); ++i)
{
if (!arSelectors[i].m_wsStyle.empty() && std::wstring::npos != arSelectors[i].m_wsStyle.find(L"page"))
{
std::map<std::wstring, std::wstring> mRules = NS_STATIC_FUNCTIONS::GetRules(arSelectors[i].m_wsStyle);
if (mRules.end() != mRules.find(L"page"))
SetPageData(oPageData, GetPageData(mRules[L"page"]), i + 1, true);
}
for (const CElement* oElement : FindElements(arNodes, arNextNodes, false))
{
std::map<std::wstring, std::wstring> mRules = oElement->GetStyle();
if (mRules.end() != mRules.find(L"page"))
SetPageData(oPageData, GetPageData(mRules[L"page"]), i + 1, true);
}
if (arSelectors[i].m_mAttributes.end() != arSelectors[i].m_mAttributes.find(L"page"))
SetPageData(oPageData, GetPageData(arSelectors[i].m_mAttributes.at(L"page")), i + 1, false);
}
return true;
}
#endif
void CCssCalculator_Private::AddStyles(const std::string &sStyle)
{
@ -784,6 +617,16 @@ namespace NSCSS
if (wsStyle.empty())
return;
std::wregex oRegex(L"@page\\s*([^{]*)(\\{[^}]*\\})");
std::wsmatch oMatch;
std::wstring::const_iterator oSearchStart(wsStyle.cbegin());
while (std::regex_search(oSearchStart, wsStyle.cend(), oMatch, oRegex))
{
AddPageData(oMatch[1].str(), oMatch[2].str());
oSearchStart = oMatch.suffix().first;
}
AddStyles(U_TO_UTF8(wsStyle));
}
@ -810,26 +653,6 @@ namespace NSCSS
CTree::CountingNumberRepetitions(oTree, *m_mStatictics);
}
void CCssCalculator_Private::SetSizeSourceWindow(const CSizeWindow &oSizeWindow)
{
m_oSourceWindow = oSizeWindow;
}
void CCssCalculator_Private::SetSizeDeviceWindow(const CSizeWindow &oSizeWindow)
{
m_oDeviceWindow = oSizeWindow;
}
CSizeWindow CCssCalculator_Private::GetSizeSourceWindow() const
{
return m_oSourceWindow;
}
CSizeWindow CCssCalculator_Private::GetSizeDeviceWindow() const
{
return m_oDeviceWindow;
}
void CCssCalculator_Private::SetUnitMeasure(const UnitMeasure& nType)
{
m_UnitMeasure = nType;
@ -863,9 +686,6 @@ namespace NSCSS
m_mData.clear();
m_arFiles.clear();
m_oDeviceWindow.Clear();
m_oSourceWindow.Clear();
}
}
inline static std::wstring StringifyValueList(const KatanaArray* oValues)

View File

@ -26,16 +26,31 @@ namespace NSCSS
std::map<std::wstring, CElement*> m_mData;
typedef struct
{
std::vector<std::wstring> m_wsNames;
std::map<std::wstring, std::wstring> m_mData;
} TPageData;
std::vector<TPageData> m_arPageDatas;
std::map<StatistickElement, unsigned int> *m_mStatictics; // Количество повторений свойств id и style у селекторов
#ifdef CSS_CALCULATOR_WITH_XHTML
std::map<std::vector<CNode>, CCompiledStyle*> m_mUsedStyles;
std::map<std::wstring, std::wstring> GetPageData(const std::wstring& wsPageName);
void SetPageData(NSProperties::CPage& oPage, const std::map<std::wstring, std::wstring>& mData, unsigned int unLevel, bool bHardMode = false);
std::vector<std::wstring> CalculateAllNodes(const std::vector<CNode>& arSelectors);
void FindPrevAndKindElements(const CElement* pElement, const std::vector<std::wstring>& arNextNodes, std::vector<CElement*>& arFindedElements, const std::wstring& wsName, const std::vector<std::wstring>& arClasses = {});
std::vector<CElement*> FindElements(std::vector<std::wstring>& arNodes, std::vector<std::wstring>& arNextNodes, bool bIsSettings);
#endif
std::wstring m_sEncoding;
CSizeWindow m_oSourceWindow;
CSizeWindow m_oDeviceWindow;
void AddPageData(const std::wstring& wsPageName, const std::wstring& wsStyles);
void GetStylesheet(const KatanaStylesheet* oStylesheet);
void GetRule(const KatanaRule* oRule);
@ -59,6 +74,8 @@ namespace NSCSS
#ifdef CSS_CALCULATOR_WITH_XHTML
CCompiledStyle GetCompiledStyle(const std::vector<CNode> &arSelectors, const bool& bIsSettings = false, const UnitMeasure& unitMeasure = Point);
bool GetCompiledStyle(CCompiledStyle& oStyle, const std::vector<CNode> &arSelectors, const bool& bIsSettings = false, const UnitMeasure& unitMeasure = Point);
bool CalculatePageStyle(NSProperties::CPage& oPageData, const std::vector<CNode> &arSelectors);
#endif
void AddStyles(const std::string& sStyle);
@ -69,12 +86,6 @@ namespace NSCSS
void SetDpi(unsigned short int nValue);
void SetBodyTree(const CTree &oTree);
void SetSizeSourceWindow(const CSizeWindow& oSizeWindow);
void SetSizeDeviceWindow(const CSizeWindow& oSizeWindow);
CSizeWindow GetSizeSourceWindow() const;
CSizeWindow GetSizeDeviceWindow() const;
UnitMeasure GetUnitMeasure() const;
std::wstring GetEncoding() const;
unsigned short int GetDpi() const;

View File

@ -173,26 +173,26 @@ namespace NSCSS
return arElements;
}
std::vector<CElement *> CElement::GetPrevElements(const std::vector<std::wstring>::reverse_iterator &arNodesRBegin, const std::vector<std::wstring>::reverse_iterator &arNodesREnd) const
std::vector<CElement *> CElement::GetPrevElements(const std::vector<std::wstring>::const_reverse_iterator& oNodesRBegin, const std::vector<std::wstring>::const_reverse_iterator& oNodesREnd) const
{
if (arNodesRBegin >= arNodesREnd || m_arPrevElements.empty())
if (oNodesRBegin >= oNodesREnd || m_arPrevElements.empty())
return std::vector<CElement*>();
std::vector<CElement*> arElements;
for (std::vector<std::wstring>::reverse_iterator iWord = arNodesRBegin; iWord != arNodesREnd; ++iWord)
for (std::vector<std::wstring>::const_reverse_iterator iWord = oNodesRBegin; iWord != oNodesREnd; ++iWord)
{
if ((*iWord)[0] == L'.' && ((*iWord).find(L" ") != std::wstring::npos))
{
std::vector<std::wstring> arClasses = NS_STATIC_FUNCTIONS::GetWordsW(*iWord, false, L" ");
for (std::wstring sClass : arClasses)
for (const std::wstring& wsClass : arClasses)
{
for (CElement* oPrevElement : m_arPrevElements)
{
if (oPrevElement->m_sSelector == sClass)
if (oPrevElement->m_sSelector == wsClass)
{
arElements.push_back(oPrevElement);
std::vector<CElement*> arTempElements = oPrevElement->GetPrevElements(iWord + 1, arNodesREnd);
std::vector<CElement*> arTempElements = oPrevElement->GetPrevElements(iWord + 1, oNodesREnd);
arElements.insert(arElements.end(), arTempElements.begin(), arTempElements.end());
}
}
@ -205,7 +205,7 @@ namespace NSCSS
if (oPrevElement->m_sSelector == *iWord)
{
arElements.push_back(oPrevElement);
std::vector<CElement*> arTempElements = oPrevElement->GetPrevElements(iWord + 1, arNodesREnd);
std::vector<CElement*> arTempElements = oPrevElement->GetPrevElements(iWord + 1, oNodesREnd);
arElements.insert(arElements.end(), arTempElements.begin(), arTempElements.end());
// return arElements;
}

View File

@ -39,7 +39,7 @@ namespace NSCSS
std::map<std::wstring, std::wstring> GetFullStyle(const std::vector<CNode>& arSelectors) const;
std::map<std::wstring, std::wstring> GetFullStyle(const std::vector<std::wstring>& arNodes) const;
std::vector<CElement *> GetNextOfKin(const std::wstring& sName, const std::vector<std::wstring>& arClasses = {}) const;
std::vector<CElement *> GetPrevElements(const std::vector<std::wstring>::reverse_iterator &arNodesRBegin, const std::vector<std::wstring>::reverse_iterator &arNodesREnd) const;
std::vector<CElement *> GetPrevElements(const std::vector<std::wstring>::const_reverse_iterator& oNodesRBegin, const std::vector<std::wstring>::const_reverse_iterator& oNodesREnd) const;
std::map<std::wstring, std::wstring> GetConvertStyle(const std::vector<CNode>& arNodes) const;
CElement *FindPrevElement(const std::wstring& sSelector) const;

View File

@ -14,23 +14,21 @@ namespace NSCSS
{
switch (enUnitMeasure)
{
case NSCSS::Pixel:
return dValue;
case NSCSS::Point:
return 72. / (double)ushDPI * dValue;
return dValue * 72. / (double)ushDPI;
case NSCSS::Cantimeter:
return dValue / (double)ushDPI * 2.54;
case NSCSS::Millimeter:
return dValue / (double)ushDPI * 25.4;
case NSCSS::Inch:
return 1. / (double)ushDPI * dValue;
return dValue / (double)ushDPI;
case NSCSS::Peak:
return 0.16667 / (double)ushDPI * dValue;
return dValue * 6. / (double)ushDPI; // 1 дюйм = 6 пик
case NSCSS::Twips:
return (dValue / (double)ushDPI) * 144.;
return dValue * 1440. / (double)ushDPI;
default:
return dValue;
}
return 0.;
}
double CUnitMeasureConverter::ConvertCm(double dValue, UnitMeasure enUnitMeasure, unsigned short ushDPI)
@ -38,22 +36,20 @@ namespace NSCSS
switch (enUnitMeasure)
{
case NSCSS::Point:
return 28.35 * dValue;
return dValue * 28.3465 ; // 1 см = (2.54 / 72) пункта
case NSCSS::Pixel:
return (double)ushDPI / 2.54 * dValue;
case NSCSS::Cantimeter:
return dValue;
return dValue * (double)ushDPI / 2.54;
case NSCSS::Millimeter:
return dValue * 10.;
case NSCSS::Inch:
return dValue / 2.54f;
return dValue / 2.54; // 1 дюйм = 2.54 см
case NSCSS::Peak:
return 2.36 * dValue;
return dValue * 2.36; // 2.36 = 6 / 2.54
case NSCSS::Twips:
return (dValue) * 0.3937 * (double)ushDPI;
return dValue * 567.; // 1 см = (1440 / 2.54) твипов
default:
return dValue;
}
return 0.;
}
double CUnitMeasureConverter::ConvertMm(double dValue, NSCSS::UnitMeasure enUnitMeasure, unsigned short ushDPI)
@ -61,22 +57,20 @@ namespace NSCSS
switch (enUnitMeasure)
{
case NSCSS::Point:
return 2.835 * dValue;
return dValue * 2.8346; // 1 мм = (25.4 / 72) пункта
case NSCSS::Pixel:
return (double)ushDPI / 25.4 * dValue;
return dValue * (double)ushDPI / 25.4;
case NSCSS::Cantimeter:
return dValue / 10.;
case NSCSS::Millimeter:
return dValue;
case NSCSS::Inch:
return dValue / 25.4;
case NSCSS::Peak:
return 0.236 * dValue;
return dValue * 0.236; // 0.236 = 6 / 25.4
case NSCSS::Twips:
return (dValue / 10.) * 0.3937 * (double)ushDPI;
return dValue * 56.7;
default:
return dValue;
}
return 0.;
}
double CUnitMeasureConverter::ConvertIn(double dValue, NSCSS::UnitMeasure enUnitMeasure, unsigned short ushDPI)
@ -84,45 +78,41 @@ namespace NSCSS
switch (enUnitMeasure)
{
case NSCSS::Point:
return dValue / 6.;
return dValue / 72.;
case NSCSS::Pixel:
return dValue * (double)ushDPI;
case NSCSS::Cantimeter:
return dValue * 2.54;
return dValue * 2.54; // 1 дюйм = 2.54 см
case NSCSS::Millimeter:
return dValue * 25.4;
case NSCSS::Inch:
return dValue;
case NSCSS::Peak:
return dValue / 72.;
return dValue * 6.;
case NSCSS::Twips:
return dValue * 144.;
return dValue * 1440.;
default:
return dValue;
}
return 0.;
}
double CUnitMeasureConverter::ConvertPt(double dValue, NSCSS::UnitMeasure enUnitMeasure, unsigned short ushDPI)
{
switch (enUnitMeasure)
{
case NSCSS::Point:
return dValue;
case NSCSS::Pixel:
return (double)ushDPI / 72. * dValue;
return dValue * (double)ushDPI / 72.;
case NSCSS::Cantimeter:
return dValue * 0.03528;
return dValue * 0.03528; // 0.03528 = 2.54 / 72
case NSCSS::Millimeter:
return dValue * 0.3528;
case NSCSS::Inch:
return dValue / 72.;
return dValue / 72.; // 1 дюйм = 72 пункта
case NSCSS::Peak:
return dValue / 12.;
return dValue * 0.0833; // 0.0833 = 6 / 72 (1 пункт = 1/72 дюйма)
case NSCSS::Twips:
return (dValue / 72.) * 144.;
return dValue * 20.; // 20 = 1440 / 72
default:
return dValue;
}
return 0.;
}
double CUnitMeasureConverter::ConvertPc(double dValue, NSCSS::UnitMeasure enUnitMeasure, unsigned short ushDPI)
@ -130,27 +120,49 @@ namespace NSCSS
switch (enUnitMeasure)
{
case NSCSS::Point:
return dValue * 12.;
return dValue * 12.; // 12 = 72 / 6
case NSCSS::Pixel:
return (double)ushDPI / 6. * dValue;
return dValue * (double)ushDPI / 6.; // 1 дюйм = 6 пика
case NSCSS::Cantimeter:
return dValue * 0.423;
return dValue * 0.423; // 0.423 = 2.54 / 6
case NSCSS::Millimeter:
return dValue * 4.23;
return dValue * 4.233; // 4.23 = 25.4 / 6
case NSCSS::Inch:
return dValue / 6.;
case NSCSS::Peak:
return dValue;
case NSCSS::Twips:
return dValue * 24.;
return dValue * 3.333; // 3.333 = 20 / 6
default:
return dValue;
}
}
double CUnitMeasureConverter::ConvertTw(double dValue, UnitMeasure enUnitMeasure, unsigned short ushDPI)
{
switch (enUnitMeasure)
{
case NSCSS::Point:
return dValue * 0.05; // 0.05 = 72. / 1440.
case NSCSS::Pixel:
return dValue * (double)ushDPI / 1440.; // 1 дюйм = 1440 твипов
case NSCSS::Cantimeter:
return dValue * 0.001764; // 0.001764 = 2.54 / 1440
case NSCSS::Millimeter:
return dValue * 0.01764;
case NSCSS::Inch:
return dValue * 1440.;
case NSCSS::Peak:
return dValue * 0.004167; // 0.004167 = 6 / 1440
default:
return dValue;
}
return 0.;
}
bool CUnitMeasureConverter::GetValue(const std::wstring &wsValue, double &dValue, UnitMeasure &enUnitMeasure)
{
std::wregex oRegex(LR"((-?\.\d+|-?\d+(\.\d+)?)\s*(px|pt|cm|mm|in|pc|%|em|rem)?)");
if (wsValue.empty() || wsValue.end() == std::find_if(wsValue.begin(), wsValue.end(), [](wchar_t wChar) { return iswdigit(wChar);}))
return false;
std::wregex oRegex(LR"((-?\.\d+|-?\d+(\.\d+)?)\s*(px|pt|cm|mm|in|pc|%|em|rem|tw)?)");
std::wsmatch oMatches;
if(!std::regex_search(wsValue, oMatches, oRegex))
@ -176,6 +188,8 @@ namespace NSCSS
enUnitMeasure = Em;
else if (L"rem" == oMatches[3])
enUnitMeasure = Rem;
else if (L"tw" == oMatches[3])
enUnitMeasure = Twips;
else
enUnitMeasure = None;

View File

@ -30,6 +30,7 @@ namespace NSCSS
static double ConvertIn(double dValue, UnitMeasure enUnitMeasure, unsigned short ushDPI);
static double ConvertPt(double dValue, UnitMeasure enUnitMeasure, unsigned short ushDPI);
static double ConvertPc(double dValue, UnitMeasure enUnitMeasure, unsigned short ushDPI);
static double ConvertTw(double dValue, UnitMeasure enUnitMeasure, unsigned short ushDPI);
static bool GetValue(const std::wstring& wsValue, double& dValue, UnitMeasure& enUnitMeasure);
};

View File

@ -2,34 +2,6 @@
namespace NSCSS
{
CSizeWindow::CSizeWindow()
: m_ushWidth(0), m_ushHeight(0)
{}
CSizeWindow::CSizeWindow(unsigned short unWidth, unsigned short unHeight)
: m_ushWidth(unWidth), m_ushHeight(unHeight)
{}
bool CSizeWindow::Empty() const
{
return ((0 == m_ushWidth) && (0 == m_ushHeight));
}
void CSizeWindow::Clear()
{
m_ushWidth = m_ushHeight = 0;
}
bool CSizeWindow::operator==(const CSizeWindow &oSizeWindow) const
{
return ((m_ushWidth == oSizeWindow.m_ushWidth) && (m_ushHeight == oSizeWindow.m_ushHeight));
}
bool CSizeWindow::operator!=(const CSizeWindow &oSizeWindow) const
{
return ((m_ushWidth != oSizeWindow.m_ushWidth) || (m_ushHeight != oSizeWindow.m_ushHeight));
}
bool StatistickElement::operator<(const StatistickElement &oStatistickElement) const
{
return sValue < oStatistickElement.sValue;
@ -98,7 +70,7 @@ namespace NSCSS
{L"deepskyblue", L"00BFFF"}, {L"dodgerblue", L"1E90FF"}, {L"cornflowerblue",L"6495ED"},
{L"mediumdlateblue", L"7B68EE"}, {L"royalblue", L"4169E1"}, {L"blue", L"0000FF"}, {L"LightCoral", L"#F08080"}, {L"LightCoral", L"#F08080"}, {L"LightCoral", L"#F08080"},
{L"mediumblue", L"0000CD"}, {L"darkblue", L"00008B"}, {L"navy", L"000080"},
{L"midnightblue", L"191970"},
{L"midnightblue", L"191970"}, {L"navyblue", L"A0B0E0"},
/* White tones */
{L"white", L"FFFFFF"}, {L"snow", L"FFFAFA"}, {L"honeydew", L"F0FFF0"},
{L"mintcream", L"F5FFFA"}, {L"azure", L"F0FFFF"}, {L"aliceblue", L"F0F8FF"},

View File

@ -16,21 +16,6 @@ namespace NSCSS
ScalingDirectionY = 2
} ScalingDirection;
struct CSizeWindow
{
unsigned short m_ushWidth;
unsigned short m_ushHeight;
CSizeWindow();
CSizeWindow(unsigned short unWidth, unsigned short unHeight);
bool Empty() const;
void Clear();
bool operator==(const CSizeWindow& oSizeWindow) const;
bool operator!=(const CSizeWindow& oSizeWindow) const;
};
struct StatistickElement
{
enum TypeElement
@ -61,66 +46,68 @@ namespace NSCSS
{
typedef enum
{
B_CustomStyle = 0,
B_StyleId = 1,
B_Type = 2,
B_Default = 3,
B_CustomStyle,
B_StyleId,
B_Type,
B_Default,
B_Name = 4,
B_BasedOn = 5,
B_QFormat = 6,
B_Link = 7,
B_UnhideWhenUsed = 8,
B_UiPriority = 9,
B_Name,
B_BasedOn,
B_QFormat,
B_Link,
B_UnhideWhenUsed,
B_UiPriority,
B_SemiHidden
} BasicProperties;
typedef enum
{
P_Jc = 0,
P_Spacing = 1,
P_ContextualSpacing = 2,
P_Ind = 3,
P_OutlineLvl = 4,
P_Shd = 5,
P_Jc,
P_Spacing,
P_ContextualSpacing,
P_Ind,
P_OutlineLvl,
P_Shd,
// <pBdr>
P_TopBorder = 6,
P_LeftBorder = 7,
P_BottomBorder = 8,
P_RightBorder = 9,
P_TopBorder,
P_LeftBorder,
P_BottomBorder,
P_RightBorder,
// </pBdr>
P_KeepLines = 10,
P_KeepNext = 11,
P_KeepLines,
P_KeepNext,
} ParagraphProperties;
typedef enum
{
R_RFonts = 0,
R_Sz = 1,
R_B = 2,
R_I = 3,
R_Color = 4,
R_U = 5,
R_Highlight = 6,
R_SmallCaps = 7
R_RFonts ,
R_Sz,
R_B,
R_I,
R_Color,
R_U,
R_Highlight,
R_SmallCaps,
R_Kern
} RunnerProperties;
typedef enum
{
T_TblInd = 0,
T_TblInd ,
// <tblCellMar>
T_CellTop = 1,
T_CellLeft = 2,
T_CellBottom = 3,
T_CellRight = 4,
T_CellTop,
T_CellLeft,
T_CellBottom,
T_CellRight,
// <tblCellMar>
// <tblBorders>
T_BorderTop = 5,
T_BorderLeft = 6,
T_BorderBottom = 7,
T_BorderRight = 8,
T_BorderInsideH = 9,
T_BorderInsideV = 10
T_BorderTop ,
T_BorderLeft,
T_BorderBottom,
T_BorderRight,
T_BorderInsideH,
T_BorderInsideV
// </tblBorders>
} TableProperties;
}

View File

@ -80,6 +80,52 @@ namespace NS_STATIC_FUNCTIONS
return arValues;
}
std::vector<std::wstring> ParseCSSPropertie(const std::wstring& wsInput)
{
std::vector<std::wstring> arResult;
std::wstring wsCurrent;
bool bInQuotes = false;
bool bInFunction = false;
int nParenDepth = 0;
for (wchar_t c : wsInput)
{
if (c == ' ' && !bInQuotes && !bInFunction)
{
if (!wsCurrent.empty())
{
arResult.push_back(wsCurrent);
wsCurrent.clear();
}
}
else if (c == '"' || c == '\'')
{
bInQuotes = !bInQuotes;
wsCurrent += c;
}
else if (c == '(')
{
bInFunction = true;
nParenDepth++;
wsCurrent += c;
}
else if (c == ')')
{
nParenDepth--;
if (nParenDepth == 0)
bInFunction = false;
wsCurrent += c;
}
else
wsCurrent += c;
}
if (!wsCurrent.empty())
arResult.push_back(wsCurrent);
return arResult;
}
std::vector<std::wstring> GetWordsW(const std::wstring& wsLine, bool bWithSigns, const std::wstring& wsDelimiters)
{
if (wsLine.empty())
@ -141,30 +187,17 @@ namespace NS_STATIC_FUNCTIONS
std::map<std::wstring, std::wstring> GetRules(const std::wstring& wsStyles)
{
if (wsStyles.empty())
return {};
std::wregex oCssPropertyRegex(L"([a-zA-Z-]+)\\s*:\\s*([^;\t\n\r\f\v]+)");
std::wsmatch oMatch;
std::wstring::const_iterator oSearchStart(wsStyles.cbegin());
std::map<std::wstring, std::wstring> mRules;
std::wstring::const_iterator oStartProperty = std::find_if_not(wsStyles.begin(), wsStyles.end(), std::iswspace);
std::wstring::const_iterator oEndProperty, oStartValue, oEndValue;
while (wsStyles.end() != oStartProperty)
while (std::regex_search(oSearchStart, wsStyles.cend(), oMatch, oCssPropertyRegex))
{
oEndProperty = std::find_if(oStartProperty, wsStyles.end(), [](const wchar_t &wcChar){ return L':' == wcChar;});
oStartValue = std::find_if_not(oEndProperty + 1, wsStyles.end(), std::iswspace);
if (wsStyles.end() == oEndProperty || wsStyles.end() == oStartValue)
break;
oEndValue = std::find_if(oStartValue, wsStyles.end(), [](const wchar_t &wcChar){ return L';' == wcChar;});
mRules.insert({std::wstring(oStartProperty, oEndProperty), std::wstring(oStartValue, oEndValue)});
if (wsStyles.end() == oEndValue)
break;
oStartProperty = std::find_if_not(oEndValue + 1, wsStyles.end(), std::iswspace);
mRules.insert(std::make_pair<std::wstring, std::wstring>(oMatch[1], oMatch[2]));
oSearchStart = oMatch.suffix().first;
}
return mRules;

View File

@ -20,6 +20,7 @@ namespace NSCSS
double ReadDouble(const std::wstring& wsValue);
std::vector<double> ReadDoubleValues(const std::wstring& wsValue);
std::vector<std::wstring> ParseCSSPropertie(const std::wstring& wsInput);
std::vector<std::wstring> GetWordsW(const std::wstring& wsLine, bool bWithSigns = false, const std::wstring& wsDelimiters = L" \n\r\t\f\v:;,!");
std::vector<unsigned short int> GetWeightSelector(const std::wstring& sSelector);
std::map<std::wstring, std::wstring> GetRules(const std::wstring& wsStyles);

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,11 @@ namespace NSCSS
}
}
static bool LevelIsSame(const CValue& oFirstValue, const CValue& oSecondValue)
{
return oFirstValue.m_unLevel == oSecondValue.m_unLevel;
}
bool operator==(const T& oValue) const { return m_oValue == oValue; }
bool operator>=(const T& oValue) const { return m_oValue >= oValue; }
bool operator<=(const T& oValue) const { return m_oValue <= oValue; }
@ -81,8 +86,8 @@ namespace NSCSS
return *this;
m_oValue = oValue.m_oValue;
m_unLevel = std::max(m_unLevel, oValue.m_unLevel);
m_bImportant = std::max(m_bImportant, oValue.m_bImportant);
m_unLevel = oValue.m_unLevel;
m_bImportant = oValue.m_bImportant;
return *this;
}
@ -124,6 +129,7 @@ namespace NSCSS
CDigit(double dValue, unsigned int unLevel, bool bImportant = false);
bool SetValue(const std::wstring& wsValue, unsigned int unLevel = 0, bool bHardMode = true) override;
bool SetValue(const CDigit& oValue);
bool Empty() const override;
bool Zero() const;
@ -144,6 +150,9 @@ namespace NSCSS
bool operator==(const double& oValue) const;
bool operator==(const CDigit& oDigit) const;
bool operator!=(const double& oValue) const;
bool operator!=(const CDigit& oDigit) const;
CDigit operator+(const CDigit& oDigit) const;
CDigit operator-(const CDigit& oDigit) const;
CDigit operator*(const CDigit& oDigit) const;
@ -229,6 +238,7 @@ namespace NSCSS
int ToInt() const override;
double ToDouble() const override;
std::wstring ToWString() const override;
std::wstring EquateToColor(const std::vector<std::pair<TRGB, std::wstring>>& arColors) const;
TRGB ToRGB() const;
};
@ -277,7 +287,7 @@ namespace NSCSS
CEnum();
bool SetValue(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode) override;
void SetMapping(const std::map<std::wstring, int>& mMap);
void SetMapping(const std::map<std::wstring, int>& mMap, int nDefaulvalue = -1);
bool Empty() const override;
void Clear() override;
@ -370,19 +380,17 @@ namespace NSCSS
bool SetColor (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetBackground(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
void InBorder();
const CColor& GetColor() const;
bool IsInBorder() const;
bool Empty() const;
bool Empty() const;
bool IsNone() const;
CBackground& operator =(const CBackground& oBackground);
CBackground& operator+=(const CBackground& oBackground);
bool operator==(const CBackground& oBackground) const;
private:
CColor m_oColor;
bool m_bInBorder;
};
class CTransform
@ -412,6 +420,8 @@ namespace NSCSS
public:
CBorderSide();
void Clear();
static void Equation(CBorderSide &oFirstBorderSide, CBorderSide &oSecondBorderSide);
bool SetValue(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
@ -429,6 +439,8 @@ namespace NSCSS
const CColor& GetColor() const;
bool Empty() const;
bool Zero() const;
bool Valid() const;
CBorderSide& operator+=(const CBorderSide& oBorderSide);
bool operator==(const CBorderSide& oBorderSide) const;
@ -440,17 +452,26 @@ namespace NSCSS
bool m_bBlock;
};
typedef enum
{
Collapse,
Separate
} BorderCollapse;
class CBorder
{
public:
CBorder();
void Clear();
static void Equation(CBorder &oFirstBorder, CBorder &oSecondBorder);
bool SetSides(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetWidth(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetStyle(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetColor(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetCollapse(const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
//Left Side
bool SetLeftSide (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
@ -480,8 +501,11 @@ namespace NSCSS
void Unblock();
bool Empty() const;
bool Zero() const;
bool EqualSides() const;
const CEnum& GetCollapse() const;
const CBorderSide& GetLeftBorder() const;
const CBorderSide& GetTopBorder() const;
const CBorderSide& GetRightBorder() const;
@ -494,6 +518,8 @@ namespace NSCSS
CBorderSide m_oTop;
CBorderSide m_oRight;
CBorderSide m_oBottom;
CEnum m_enCollapse;
};
class CTextDecorationLine
@ -513,6 +539,7 @@ namespace NSCSS
bool LineThrough() const;
CTextDecorationLine &operator+=(const CTextDecorationLine& oTextDecoration);
bool operator==(const CTextDecorationLine& oTextDecorationLine) const;
};
struct TTextDecoration
@ -522,6 +549,7 @@ namespace NSCSS
CColor m_oColor;
TTextDecoration& operator+=(const TTextDecoration& oTextDecoration);
bool operator==(const TTextDecoration& oTextDecoration) const;
};
class CText
@ -561,33 +589,40 @@ namespace NSCSS
public:
CIndent();
void Clear();
static void Equation(CIndent &oFirstMargin, CIndent &oSecondMargin);
bool Equals() const;
void SetPermisson(bool bPermission);
bool AddValue (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool AddLeft (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool AddTop (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool AddRight (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool AddBottom (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
void UpdateAll(double dFontSize);
void UpdateLeft(double dFontSize);
void UpdateTop(double dFontSize);
void UpdateRight(double dFontSize);
void UpdateBottom(double dFontSize);
bool SetValues (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetTop (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetRight (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetBottom (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetLeft (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
void UpdateAll (double dFontSize);
void UpdateTop (double dFontSize);
void UpdateRight (double dFontSize);
void UpdateBottom(double dFontSize);
void UpdateLeft (double dFontSize);
const CDigit& GetLeft () const;
const CDigit& GetTop () const;
const CDigit& GetRight () const;
const CDigit& GetBottom() const;
const CDigit& GetLeft () const;
bool Empty() const;
bool Zero() const;
CIndent& operator+=(const CIndent& oMargin);
bool operator==(const CIndent& oMargin) const;
CIndent& operator+=(const CIndent& oIndent);
bool operator==(const CIndent& oIndent) const;
bool operator!=(const CIndent& oIndent) const;
private:
bool AddValue(CDigit& oValue, const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetValues(const std::wstring& wsTopValue, const std::wstring& wsRightValue, const std::wstring& wsBottomValue, const std::wstring& wsLeftValue, unsigned int unLevel, bool bHardMode = false);
void UpdateSide(CDigit& oSide, double dFontSize);
CDigit m_oLeft;
CDigit m_oTop;
@ -623,6 +658,7 @@ namespace NSCSS
const CDigit& GetSize() const;
const CDigit& GetLineHeight() const;
CDigit& GetLineHeight();
const CString& GetFamily() const;
const CString& GetStretch() const;
const CString& GetStyle() const;
@ -642,8 +678,29 @@ namespace NSCSS
CString m_oStyle;
CString m_oVariant;
CString m_oWeight;
};
TTextDecoration m_oTextDecoration;
class CPage
{
public:
CPage();
bool SetMargin (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetSize (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetFooter (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
bool SetHeader (const std::wstring& wsValue, unsigned int unLevel, bool bHardMode = false);
const CDigit& GetWidth() const;
const CDigit& GetHeight() const;
const CIndent& GetMargin() const;
const CDigit& GetFooter() const;
const CDigit& GetHeader() const;
private:
CDigit m_oWidth;
CDigit m_oHeight;
CIndent m_oMargin;
CDigit m_oFooter;
CDigit m_oHeader;
};
}
}

View File

@ -6,34 +6,31 @@
#include <algorithm>
#include <list>
#define DEFAULT_LINEHEIGHT 240
#define LINEHEIGHTSCALE 10 // Значение LineHeight в OOXML должно быть в 10 раз больше чем указано в стиле
#define LINEHEIGHTCOEF 24 // Используется когда необходимо перевести в twips значение
#define POINTCOEF 20 // Используется для конвертации в OOXML значение интервала между абзацами (Измерение в двадцатых долях от точки)
#define PAGEWIDTH (12240 / POINTCOEF)
#define PAGEHEIGHT (15840 / POINTCOEF)
#define DOUBLE_TO_INTW(dValue) std::to_wstring(static_cast<int>(dValue + 0.5))
namespace NSCSS
{
CStyleUsed::CStyleUsed(const CCompiledStyle &oStyle, bool bIsPStyle)
: m_oStyle(oStyle), m_bIsPStyle(bIsPStyle)
CStyleUsed::CStyleUsed(const std::wstring &wsId, bool bIsPStyle)
: m_bIsPStyle(bIsPStyle), m_wsId(wsId)
{}
bool CStyleUsed::operator==(const CStyleUsed &oUsedStyle) const
{
return (m_bIsPStyle == oUsedStyle.m_bIsPStyle) && (m_oStyle == oUsedStyle.m_oStyle);
return (m_bIsPStyle == oUsedStyle.m_bIsPStyle) && (m_wsId == oUsedStyle.m_wsId);
}
std::wstring CStyleUsed::getId()
{
return m_sId;
if (m_bIsPStyle)
return m_wsId;
return m_wsId + L"-c";
}
void CStyleUsed::setId(const std::wstring &sId)
{
m_sId = sId;
m_wsId = sId;
}
CDocumentStyle::CDocumentStyle() : m_arStandardStyles({L"a", L"li", L"h1", L"h2", L"h3", L"h4", L"h5", L"h6", L"h1-c",
@ -157,6 +154,7 @@ namespace NSCSS
if (!oParentStyle.Empty())
{
oParentStyle.AddBasicProperties(BProperties::B_BasedOn, L"normal");
oParentStyle.AddBasicProperties(BProperties::B_StyleId, L"(" + oParentStyle.GetStyleId() + L")");
if (!bIsPStyle)
{
@ -274,152 +272,168 @@ namespace NSCSS
void CDocumentStyle::SetPStyle (const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement)
{
ConvertStyle(oStyle, oXmlElement, true);
if (oStyle.Empty() && oXmlElement.Empty())
if (oStyle.Empty())
return;
oXmlElement.AddPropertiesInP(PProperties::P_Jc, oStyle.m_oText.GetAlign().ToWString());
const bool bInTable{oStyle.HaveThisParent(L"table")};
std::wstring wsTextAlign{oStyle.m_oText.GetAlign().ToWString()};
if (wsTextAlign.empty() && bInTable)
wsTextAlign = oStyle.m_oDisplay.GetHAlign().ToWString();
oXmlElement.AddPropertiesInP(PProperties::P_Jc, wsTextAlign);
std::wstring sInfValue;
sInfValue.reserve(64);
//TODO:: проверить Permission в Margin
if (!oStyle.m_oMargin.Empty() || !oStyle.m_oPadding.Empty() /*&& oStyle.m_oMargin.GetPermission()*/)
{
const double dLeftSide = oStyle.m_oMargin.GetLeft() .ToDouble(NSCSS::Twips) + oStyle.m_oPadding.GetLeft() .ToDouble(NSCSS::Twips);
const double dRightSide = oStyle.m_oMargin.GetRight().ToDouble(NSCSS::Twips) + oStyle.m_oPadding.GetRight().ToDouble(NSCSS::Twips);
if (!oStyle.m_oMargin.GetLeft().Empty() && !oStyle.m_oMargin.GetLeft().Zero())
sInfValue += L"w:left=\"" + std::to_wstring(oStyle.m_oMargin.GetLeft().ToInt(NSCSS::Twips)) + L"\" ";
sInfValue += L"w:left=\"" + DOUBLE_TO_INTW(dLeftSide * POINTCOEF) + L"\" ";
sInfValue += L"w:right=\"" + DOUBLE_TO_INTW(dRightSide * POINTCOEF) + L"\" ";
}
if (!oStyle.m_oMargin.GetRight().Empty() && !oStyle.m_oMargin.GetRight().Zero())
sInfValue += L"w:right=\"" + std::to_wstring(oStyle.m_oMargin.GetRight().ToInt(NSCSS::Twips)) + L"\" ";
const double dIndent = oStyle.m_oText.GetIndent().ToDouble(NSCSS::Twips);
if (0. != dIndent)
sInfValue += L"w:firstLine=\"" + DOUBLE_TO_INTW(dIndent) + L"\" ";
const int nIndent = oStyle.m_oText.GetIndent().ToInt(NSCSS::Twips);
if (0 != nIndent)
sInfValue += L"w:firstLine=\"" + std::to_wstring(nIndent) + L"\" ";
oXmlElement.AddPropertiesInP(PProperties::P_Ind, sInfValue);
std::wstring sSpacingValue;
sSpacingValue.reserve(128);
//TODO:: проверить Permission в Margin
if (!oStyle.m_oMargin.Empty() || !oStyle.m_oPadding.Empty()/*&& oStyle.m_oMargin.GetPermission()*/)
{
const double dSpacingBottom = oStyle.m_oMargin.GetBottom().ToDouble(NSCSS::Twips) + oStyle.m_oPadding.GetBottom().ToDouble(NSCSS::Twips);
const double dSpacingTop = oStyle.m_oMargin.GetTop() .ToDouble(NSCSS::Twips) + oStyle.m_oPadding.GetTop() .ToDouble(NSCSS::Twips);;
sSpacingValue += L" w:after=\"" + DOUBLE_TO_INTW(dSpacingBottom * POINTCOEF) + L"\" ";
sSpacingValue += L" w:before=\"" + DOUBLE_TO_INTW(dSpacingTop * POINTCOEF) + L"\" ";
}
else/* if (!oStyle.m_pBorder.Empty() || !oStyle.m_oMargin.GetPermission())*/
sSpacingValue += L"w:after=\"0\" w:before=\"0\"";
if (!oStyle.m_oMargin.GetTop().Empty() && !oStyle.m_oMargin.GetTop().Zero())
sSpacingValue += L"w:before=\"" + std::to_wstring(oStyle.m_oMargin.GetTop().ToInt(NSCSS::Twips)) + L"\" ";
std::wstring wsLineHeight;
if (!oStyle.m_oFont.GetLineHeight().Empty())
{
double dLineHeight = oStyle.m_oFont.GetLineHeight().ToDouble(NSCSS::Twips, LINEHEIGHTCOEF) * LINEHEIGHTSCALE;
if (!oStyle.m_oMargin.GetBottom().Empty() && !oStyle.m_oMargin.GetBottom().Zero())
sSpacingValue += L"w:after=\"" + std::to_wstring(oStyle.m_oMargin.GetBottom().ToInt(NSCSS::Twips)) + L"\" ";
if (NSCSS::None == oStyle.m_oFont.GetLineHeight().GetUnitMeasure())
dLineHeight *= LINEHEIGHTCOEF;
if (0. != dLineHeight)
wsLineHeight = DOUBLE_TO_INTW(dLineHeight);
}
if (!wsLineHeight.empty())
if (!oStyle.m_oFont.GetLineHeight().Empty() && !oStyle.m_oFont.GetLineHeight().Zero())
{
sSpacingValue += L" w:line=\"" + wsLineHeight + L"\" w:lineRule=\"auto\"";
const std::wstring wsLine{std::to_wstring(oStyle.m_oFont.GetLineHeight().ToInt(NSCSS::Twips, DEFAULT_LINEHEIGHT))};
const std::wstring wsLineRule{(NSCSS::Percent == oStyle.m_oFont.GetLineHeight().GetUnitMeasure() ? L"auto" : L"atLeast")};
sSpacingValue += L" w:line=\"" + wsLine + L"\" w:lineRule=\"" + wsLineRule + L"\"";
}
// else if (!oStyle.m_oBorder.Empty())
// {
// sSpacingValue += L" w:line=\"" + std::to_wstring(static_cast<short int>(oStyle.m_oFont.GetSize().ToDouble(NSCSS::Twips) * 2 * POINTCOEF + 0.5f)) + L"\" w:lineRule=\"auto\"";
// }
else if (!oStyle.m_oBorder.Empty())
sSpacingValue += L" w:line=\"240\" w:lineRule=\"auto\" ";
if (!sSpacingValue.empty())
{
oXmlElement.AddPropertiesInP(PProperties::P_Spacing, sSpacingValue);
oXmlElement.AddPropertiesInP(PProperties::P_ContextualSpacing, L"true");
}
if (!oStyle.m_oBackground.Empty())
{
const std::wstring wsColor = oStyle.m_oBackground.GetColor().ToWString();
if (wsColor != L"ffffff")
oXmlElement.AddPropertiesInP(PProperties::P_Shd, wsColor);
}
if (!oStyle.m_oBackground.Empty() && !bInTable)
oXmlElement.AddPropertiesInP(PProperties::P_Shd, oStyle.m_oBackground.IsNone() ? L"auto" : oStyle.m_oBackground.GetColor().ToWString());
if (!oStyle.m_oBorder.Empty())
if (!oStyle.m_oBorder.Empty() && !bInTable)
{
if (oStyle.m_oBorder.EqualSides())
{
const std::wstring sBorderColor = oStyle.m_oBorder.GetLeftBorder().GetColor().ToWString();
const std::wstring sBorderStyle = oStyle.m_oBorder.GetLeftBorder().GetStyle().ToWString();
const std::wstring sBorderWidth = oStyle.m_oBorder.GetLeftBorder().GetWidth().ToWString();
const std::wstring sBorder = L" w:color=\"" + sBorderColor + L"\" w:space=\"0\" w:sz=\"" +
sBorderWidth + L"\" w:val=\"" + sBorderStyle + L"\"";
oXmlElement.AddPropertiesInP(PProperties::P_TopBorder, sBorder);
oXmlElement.AddPropertiesInP(PProperties::P_LeftBorder, sBorder);
oXmlElement.AddPropertiesInP(PProperties::P_BottomBorder, sBorder);
oXmlElement.AddPropertiesInP(PProperties::P_RightBorder, sBorder);
SetBorderStyle(oStyle, oXmlElement, PProperties::P_TopBorder);
SetBorderStyle(oStyle, oXmlElement, PProperties::P_LeftBorder);
SetBorderStyle(oStyle, oXmlElement, PProperties::P_BottomBorder);
SetBorderStyle(oStyle, oXmlElement, PProperties::P_RightBorder);
}
else
{
if (!oStyle.m_oBorder.GetTopBorder().Empty())
{
const std::wstring sBorderColor = oStyle.m_oBorder.GetTopBorder().GetColor().ToWString();
const std::wstring sBorderStyle = oStyle.m_oBorder.GetTopBorder().GetStyle().ToWString();
const std::wstring sBorderWidth = oStyle.m_oBorder.GetTopBorder().GetWidth().ToWString();
const std::wstring sBorder = L" w:color=\"" + sBorderColor + L"\" w:space=\"4\" w:sz=\"" +
sBorderWidth + L"\" w:val=\"" + sBorderStyle + L"\"";
oXmlElement.AddPropertiesInP(PProperties::P_TopBorder, sBorder);
}
SetBorderStyle(oStyle, oXmlElement, PProperties::P_TopBorder);
if (!oStyle.m_oBorder.GetRightBorder().Empty())
{
const std::wstring sBorderColor = oStyle.m_oBorder.GetRightBorder().GetColor().ToWString();
const std::wstring sBorderStyle = oStyle.m_oBorder.GetRightBorder().GetStyle().ToWString();
const std::wstring sBorderWidth = oStyle.m_oBorder.GetRightBorder().GetWidth().ToWString();
const std::wstring sBorder = L" w:color=\"" + sBorderColor + L"\" w:space=\"4\" w:sz=\"" +
sBorderWidth + L"\" w:val=\"" + sBorderStyle + L"\"";
oXmlElement.AddPropertiesInP(PProperties::P_RightBorder, sBorder);
}
SetBorderStyle(oStyle, oXmlElement, PProperties::P_RightBorder);
if (!oStyle.m_oBorder.GetBottomBorder().Empty())
{
const std::wstring sBorderColor = oStyle.m_oBorder.GetBottomBorder().GetColor().ToWString();
const std::wstring sBorderStyle = oStyle.m_oBorder.GetBottomBorder().GetStyle().ToWString();
const std::wstring sBorderWidth = oStyle.m_oBorder.GetBottomBorder().GetWidth().ToWString();
const std::wstring sBorder = L" w:color=\"" + sBorderColor + L"\" w:space=\"4\" w:sz=\"" +
sBorderWidth + L"\" w:val=\"" + sBorderStyle + L"\"";
oXmlElement.AddPropertiesInP(PProperties::P_BottomBorder, sBorder);
}
SetBorderStyle(oStyle, oXmlElement, PProperties::P_BottomBorder);
if (!oStyle.m_oBorder.GetLeftBorder().Empty())
{
const std::wstring sBorderColor = oStyle.m_oBorder.GetLeftBorder().GetColor().ToWString();
const std::wstring sBorderStyle = oStyle.m_oBorder.GetLeftBorder().GetStyle().ToWString();
const std::wstring sBorderWidth = oStyle.m_oBorder.GetLeftBorder().GetWidth().ToWString();
const std::wstring sBorder = L" w:color=\"" + sBorderColor + L"\" w:space=\"4\" w:sz=\"" +
sBorderWidth + L"\" w:val=\"" + sBorderStyle + L"\"";
oXmlElement.AddPropertiesInP(PProperties::P_LeftBorder, sBorder);
}
SetBorderStyle(oStyle, oXmlElement, PProperties::P_LeftBorder);
}
}
}
void CDocumentStyle::SetBorderStyle(const CCompiledStyle &oStyle, CXmlElement &oXmlElement, const PProperties &enBorderProperty)
{
const NSCSS::NSProperties::CBorderSide* pBorder = NULL;
const NSCSS::NSProperties::CDigit* pPadding = NULL;
switch(enBorderProperty)
{
case PProperties::P_BottomBorder:
{
pBorder = &oStyle.m_oBorder.GetBottomBorder();
pPadding = &oStyle.m_oPadding.GetBottom();
break;
}
case PProperties::P_LeftBorder:
{
pBorder = &oStyle.m_oBorder.GetLeftBorder();
pPadding = &oStyle.m_oPadding.GetLeft();
break;
}
case PProperties::P_RightBorder:
{
pBorder = &oStyle.m_oBorder.GetRightBorder();
pPadding = &oStyle.m_oPadding.GetRight();
break;
}
case PProperties::P_TopBorder:
{
pBorder = &oStyle.m_oBorder.GetTopBorder();
pPadding = &oStyle.m_oPadding.GetTop();
break;
}
default:
return;
}
oXmlElement.AddPropertiesInP(enBorderProperty, CalculateBorderStyle(*pBorder, pPadding));
}
std::wstring CDocumentStyle::CalculateBorderStyle(const NSProperties::CBorderSide &oBorder, const NSProperties::CDigit *pPadding)
{
if (oBorder.Empty())
return L"";
std::wstring wsColor = oBorder.GetColor().ToWString();
std::wstring wsStyle = oBorder.GetStyle().ToWString();
int nWidth = static_cast<int>(std::round(oBorder.GetWidth().ToDouble(Point) * 8.));
if (L"double" == wsStyle)
nWidth /= 3; // в ooxml double граница формируется из трёх линий
if (nWidth <= 3)
nWidth = 2;
else if (nWidth <= 5)
nWidth = 4;
else if (nWidth <= 7)
nWidth = 6;
else if (nWidth <= 9)
nWidth = 8;
else if (nWidth <= 15)
nWidth = 12;
else if (nWidth <= 21)
nWidth = 18;
else if (nWidth <= 29)
nWidth = 24;
else if (nWidth <= 41)
nWidth = 36;
else
nWidth = 48;
if (wsColor.empty())
wsColor = L"auto";
if (wsStyle.empty())
wsStyle = L"single";
int nSpace{0};
if (NULL != pPadding && !pPadding->Empty() && !pPadding->Zero())
nSpace = pPadding->ToInt(NSCSS::Point);
return L"w:val=\"" + wsStyle + L"\" w:sz=\"" + std::to_wstring(nWidth) + + L"\" w:space=\"" + std::to_wstring(nSpace) + L"\" w:color=\"" + wsColor + L"\"";
}
void CDocumentStyle::SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement)
{
ConvertStyle(oStyle, oXmlElement, false);
@ -427,94 +441,131 @@ namespace NSCSS
return;
if (!oStyle.m_oFont.GetSize().Empty())
oXmlElement.AddPropertiesInR(RProperties::R_Sz, DOUBLE_TO_INTW(oStyle.m_oFont.GetSize().ToDouble(NSCSS::Twips)));
oXmlElement.AddPropertiesInR(RProperties::R_Sz, std::to_wstring(static_cast<int>(oStyle.m_oFont.GetSize().ToDouble(NSCSS::Point) * 2. + 0.5))); // Значения шрифта увеличивает на 2
if (oStyle.m_oText.GetDecoration().m_oLine.Underline())
oXmlElement.AddPropertiesInR(RProperties::R_U, (!oStyle.m_oText.GetDecoration().m_oStyle.Empty()) ? oStyle.m_oText.GetDecoration().m_oStyle.ToWString() : L"single");
const std::wstring wsHighlight{oStyle.m_oBackground.GetColor().EquateToColor({{{0, 0, 0}, L"black"}, {{0, 0, 255}, L"blue"}, {{0, 255, 255}, L"cyan"},
{{0, 255, 0}, L"green"}, {{255, 0, 255}, L"magenta"}, {{255, 0, 0}, L"red"},
{{255, 255, 0}, L"yellow"}, {{255, 255, 255}, L"white"}, {{0, 0, 139}, L"darkBlue"},
{{0, 139, 139}, L"darkCyan"}, {{0, 100, 0}, L"darkGreen"}, {{139, 0, 139}, L"darkMagenta"},
{{139, 0, 0}, L"darkRed"}, {{128, 128, 0}, L"darkYellow"},{{169, 169, 169}, L"darkGray"},
{{211, 211, 211}, L"lightGray"}})};
if (L"none" != wsHighlight)
oXmlElement.AddPropertiesInR(RProperties::R_Highlight, wsHighlight);
oXmlElement.AddPropertiesInR(RProperties::R_Highlight, oStyle.m_oBackground.GetColor().ToWString());
oXmlElement.AddPropertiesInR(RProperties::R_Color, oStyle.m_oText.GetColor().ToWString());
oXmlElement.AddPropertiesInR(RProperties::R_U, (oStyle.m_oText.GetDecoration().m_oLine.Underline()) ? L"underline" : L"");
std::wstring wsFontFamily{oStyle.m_oFont.GetFamily().ToWString()};
if (L"sans-serif" == wsFontFamily)
wsFontFamily = L"Arial";
else if (L"serif" == wsFontFamily)
wsFontFamily = L"Times New Roman";
oXmlElement.AddPropertiesInR(RProperties::R_RFonts, oStyle.m_oFont.GetFamily().ToWString());
oXmlElement.AddPropertiesInR(RProperties::R_I, oStyle.m_oFont.GetStyle().ToWString());
oXmlElement.AddPropertiesInR(RProperties::R_B, oStyle.m_oFont.GetWeight().ToWString());
oXmlElement.AddPropertiesInR(RProperties::R_SmallCaps, oStyle.m_oFont.GetVariant().ToWString());
}
void CDocumentStyle::WriteRStyle (const NSCSS::CCompiledStyle& oStyle)
bool CDocumentStyle::WriteRStyle(const NSCSS::CCompiledStyle& oStyle)
{
Clear();
if(oStyle.GetId().empty())
{
m_sId = L"normal";
return;
return false;
}
CStyleUsed structStyle(oStyle, false);
CStyleUsed structStyle(oStyle.GetId(), false);
std::list<CStyleUsed>::iterator oItem = std::find(m_arStyleUsed.begin(), m_arStyleUsed.end(), structStyle);
if (oItem != m_arStyleUsed.end())
{
m_sId = (*oItem).getId();
return;
return true;
}
CXmlElement oXmlElement;
SetRStyle(oStyle, oXmlElement);
if (!oStyle.Empty() || !oXmlElement.Empty())
{
structStyle.setId(oXmlElement.GetStyleId());
m_arStyleUsed.push_back(structStyle);
m_sStyle += oXmlElement.GetRStyle();
}
if (oXmlElement.Empty())
return false;
m_arStyleUsed.push_back(structStyle);
m_sStyle += oXmlElement.GetRStyle();
return true;
}
void CDocumentStyle::WriteLitePStyle(const CCompiledStyle &oStyle)
bool CDocumentStyle::WriteLitePStyle(const CCompiledStyle &oStyle)
{
if (oStyle.Empty())
return;
return false;
CXmlElement oXmlElement;
SetPStyle(oStyle, oXmlElement);
if (!oXmlElement.Empty())
m_sStyle += oXmlElement.GetPStyle(true);
if (oXmlElement.Empty())
return false;
m_sStyle += oXmlElement.GetPStyle(true);
return true;
}
void CDocumentStyle::WriteLiteRStyle(const CCompiledStyle &oStyle)
bool CDocumentStyle::WriteLiteRStyle(const CCompiledStyle &oStyle)
{
if (oStyle.Empty())
return;
return false;
CXmlElement oXmlElement;
SetRStyle(oStyle, oXmlElement);
if (!oXmlElement.Empty())
m_sStyle += oXmlElement.GetRStyle(true);
if (oXmlElement.Empty())
return false;
m_sStyle += oXmlElement.GetRStyle(true);
return true;
}
void CDocumentStyle::WritePStyle (const NSCSS::CCompiledStyle& oStyle)
bool CDocumentStyle::WritePStyle(const NSCSS::CCompiledStyle& oStyle)
{
Clear();
if(oStyle.GetId().empty())
{
m_sId = L"normal";
return;
return true;
}
CStyleUsed structStyle(oStyle, true);
CStyleUsed structStyle(oStyle.GetId(), true);
std::list<CStyleUsed>::iterator oItem = std::find(m_arStyleUsed.begin(), m_arStyleUsed.end(), structStyle);
if (oItem != m_arStyleUsed.end())
{
m_sId = (*oItem).getId();
return;
return true;
}
CXmlElement oXmlElement;
SetPStyle(oStyle, oXmlElement);
if (!oStyle.Empty() || !oXmlElement.Empty())
{
structStyle.setId(oXmlElement.GetStyleId());
m_arStyleUsed.push_back(structStyle);
m_sStyle += oXmlElement.GetPStyle();
}
if (oXmlElement.Empty())
return false;
structStyle.setId(oXmlElement.GetStyleId());
if (structStyle.getId().empty())
structStyle.setId(m_sId);
m_arStyleUsed.push_back(structStyle);
m_sStyle += oXmlElement.GetPStyle();
return true;
}
}

View File

@ -10,12 +10,11 @@ namespace NSCSS
{
class CStyleUsed
{
CCompiledStyle m_oStyle;
bool m_bIsPStyle;
std::wstring m_sId;
std::wstring m_wsId;
public:
CStyleUsed(const CCompiledStyle& oStyle, bool bIsPStyle);
CStyleUsed(const std::wstring& wsId, bool bIsPStyle);
bool operator==(const CStyleUsed& oUsedStyle) const;
@ -43,14 +42,15 @@ namespace NSCSS
void SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement);
void SetPStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement);
void SetBorderStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement, const PProperties& enBorderProperty);
public:
CDocumentStyle();
~CDocumentStyle();
void WritePStyle(const NSCSS::CCompiledStyle& oStyle);
void WriteRStyle(const NSCSS::CCompiledStyle& oStyle);
void WriteLitePStyle(const NSCSS::CCompiledStyle& oStyle);
void WriteLiteRStyle(const NSCSS::CCompiledStyle& oStyle);
bool WritePStyle(const NSCSS::CCompiledStyle& oStyle);
bool WriteRStyle(const NSCSS::CCompiledStyle& oStyle);
bool WriteLitePStyle(const NSCSS::CCompiledStyle& oStyle);
bool WriteLiteRStyle(const NSCSS::CCompiledStyle& oStyle);
void SetStyle(const std::wstring& sStyle);
void SetId (const std::wstring& sId);
@ -59,6 +59,8 @@ namespace NSCSS
std::wstring GetIdAndClear();
void Clear();
static std::wstring CalculateBorderStyle(const NSCSS::NSProperties::CBorderSide& oBorder, const NSCSS::NSProperties::CDigit* pPadding = NULL);
};
}
#endif // CDOCUMENTSTYLE_H

View File

@ -27,7 +27,7 @@ CXmlElement::CXmlElement(const std::wstring& sNameDefaultElement)
bool CXmlElement::Empty() const
{
return m_mBasicValues.empty() && m_mPStyleValues.empty() && m_mRStyleValues.empty();
return m_mPStyleValues.empty() && m_mRStyleValues.empty() && m_mBasicValues.find(CSSProperties::BasicProperties::B_BasedOn) == m_mBasicValues.end();
}
void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
@ -35,7 +35,19 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
if (!Empty())
Clear();
if (sNameDefaultElement == L"li")
if (sNameDefaultElement == L"p")
{
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"paragraph");
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"p");
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Normal (Web)");
AddBasicProperties(CSSProperties::BasicProperties::B_BasedOn, L"normal");
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"99");
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddBasicProperties(CSSProperties::BasicProperties::B_SemiHidden, L"true");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"li")
{
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"paragraph");
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"li");
@ -55,7 +67,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h1-c");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"0");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:after=\"0\" w:before=\"480\"");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"h2")
{
@ -66,7 +78,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h2-c");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"1");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:after=\"0\" w:before=\"400\"");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"h3")
{
@ -77,7 +89,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h3-c");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"2");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:after=\"0\" w:before=\"360\"");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"h4")
{
@ -88,7 +100,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h4-c");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"3");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:after=\"0\" w:before=\"320\"");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"h5")
{
@ -99,7 +111,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h5-c");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"4");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:after=\"0\" w:before=\"280\"");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"h6")
@ -111,7 +123,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h6-c");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_OutlineLvl, L"5");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:after=\"0\" w:before=\"280\"");
AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\"");
}
else if (sNameDefaultElement == L"h1-c")
{
@ -122,9 +134,9 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"9");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h1");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"44");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"48");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Kern, L"36");
}
else if (sNameDefaultElement == L"h2-c")
{
@ -136,9 +148,8 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h2");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"33");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"36");
}
else if (sNameDefaultElement == L"h3-c")
{
@ -150,9 +161,8 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h3");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"26");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"27");
}
else if (sNameDefaultElement == L"h4-c")
{
@ -164,9 +174,8 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h4");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"24");
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"22");
}
else if (sNameDefaultElement == L"h5-c")
{
@ -178,9 +187,8 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h5");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"20");
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"18");
}
else if (sNameDefaultElement == L"h6-c")
{
@ -192,28 +200,8 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"h6");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"15");
}
else if (sNameDefaultElement == L"p-c")
{
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"character");
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"p-c");
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Paragraph character");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"p");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
}
else if (sNameDefaultElement == L"p")
{
AddBasicProperties(CSSProperties::BasicProperties::B_Type, L"paragraph");
AddBasicProperties(CSSProperties::BasicProperties::B_StyleId, L"p");
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Paragraph");
AddBasicProperties(CSSProperties::BasicProperties::B_BasedOn, L"normal");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"p-c");
AddPropertiesInR(CSSProperties::RunnerProperties::R_B, L"bold");
}
else if (sNameDefaultElement == L"div-c")
{
@ -222,8 +210,6 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_CustomStyle, L"1");
AddBasicProperties(CSSProperties::BasicProperties::B_Name, L"Div character");
AddBasicProperties(CSSProperties::BasicProperties::B_Link, L"div");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
}
else if (sNameDefaultElement == L"div")
{
@ -242,9 +228,9 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement)
AddBasicProperties(CSSProperties::BasicProperties::B_UiPriority, L"99");
AddBasicProperties(CSSProperties::BasicProperties::B_UnhideWhenUsed, L"true");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Sz, L"24");
AddPropertiesInR(CSSProperties::RunnerProperties::R_Color, L"0000FF");
AddPropertiesInR(CSSProperties::RunnerProperties::R_U, L"single");
AddPropertiesInR(CSSProperties::RunnerProperties::R_RFonts, DEFAULTFONTNAME);
}
else if (sNameDefaultElement == L"a")
{
@ -364,22 +350,22 @@ std::wstring CXmlElement::ConvertPStyle(bool bIsLite) const
case CSSProperties::ParagraphProperties::P_TopBorder:
{
sPBdr += L"<w:top" + oItem.second + L"/>";
sPBdr += L"<w:top " + oItem.second + L"/>";
break;
}
case CSSProperties::ParagraphProperties::P_LeftBorder:
{
sPBdr += L"<w:left" + oItem.second + L"/>";
sPBdr += L"<w:left " + oItem.second + L"/>";
break;
}
case CSSProperties::ParagraphProperties::P_BottomBorder:
{
sPBdr += L"<w:bottom" + oItem.second + L"/>";
sPBdr += L"<w:bottom " + oItem.second + L"/>";
break;
}
case CSSProperties::ParagraphProperties::P_RightBorder:
{
sPBdr += L"<w:right" + oItem.second + L"/>";
sPBdr += L"<w:right " + oItem.second + L"/>";
break;
}
case CSSProperties::ParagraphProperties::P_KeepLines:
@ -429,8 +415,8 @@ std::wstring CXmlElement::ConvertRStyle(bool bIsLite) const
}
case CSSProperties::RunnerProperties::R_Sz:
{
sRStyle += L"<w:sz w:val=\"" + oItem.second +
L"\"/>" + L"<w:szCs w:val=\"" + oItem.second + L"\"/>";
sRStyle += L"<w:sz w:val=\"" + oItem.second + L"\"/>" +
L"<w:szCs w:val=\"" + oItem.second + L"\"/>";
break;
}
case CSSProperties::RunnerProperties::R_B:
@ -462,11 +448,12 @@ std::wstring CXmlElement::ConvertRStyle(bool bIsLite) const
sRStyle += L"<w:u w:val=\"" + oItem.second + L"\"/>";
break;
}
// case CSSProperties::RunnerProperties::R_Highlight:
// {
// sRStyle += L"<w:highlight w:val=\"" + oItem.second + L"\"/>";
// break;
// }
case CSSProperties::RunnerProperties::R_Highlight:
{
if (!oItem.second.empty())
sRStyle += L"<w:highlight w:val=\"" + oItem.second + L"\"/>";
break;
}
case CSSProperties::RunnerProperties::R_SmallCaps:
{
if (oItem.second == L"smallCaps")
@ -475,6 +462,11 @@ std::wstring CXmlElement::ConvertRStyle(bool bIsLite) const
sRStyle += L"<w:smallCaps w:val=\"false\"/>";
break;
}
case CSSProperties::RunnerProperties::R_Kern:
{
sRStyle += L"<w:kern w:val=\"" + oItem.second + L"\"/>";
break;
}
default:
break;
}
@ -519,7 +511,8 @@ std::wstring CXmlElement::ConvertBasicInfoStyle() const
}
case CSSProperties::BasicProperties::B_UnhideWhenUsed:
{
sBasicInfo += L"<w:unhideWhenUsed/>";
if (L"true" == oItem.second)
sBasicInfo += L"<w:unhideWhenUsed/>";
break;
}
case CSSProperties::BasicProperties::B_UiPriority:
@ -527,6 +520,12 @@ std::wstring CXmlElement::ConvertBasicInfoStyle() const
sBasicInfo += L"<w:uiPriority w:val=\"" + oItem.second + L"\"/>";
break;
}
case CSSProperties::BasicProperties::B_SemiHidden:
{
if (L"true" == oItem.second)
sBasicInfo += L"<w:semiHidden/>";
break;
}
default:
break;
}
@ -598,7 +597,7 @@ std::wstring CXmlElement::GetPStyle(bool bIsLite) const
{
if (bIsLite)
return ConvertPStyle(true);
return GetStyle(true, true, false);
}
@ -606,7 +605,7 @@ std::wstring CXmlElement::GetRStyle(bool bIsLite) const
{
if (bIsLite)
return ConvertRStyle(true);
return GetStyle(true, false, true);
}

View File

@ -11,7 +11,9 @@
#include "../../../DesktopEditor/common/File.h"
#include "../../../DesktopEditor/common/Directory.h"
#include "../../../DesktopEditor/common/StringBuilder.h"
#include "../../../DesktopEditor/xml/include/xmlutils.h"
#include "../../../UnicodeConverter/UnicodeConverter.h"
#include "../../../HtmlFile2/src/StringFinder.h"
static std::string nonbreaking_inline = "|a|abbr|acronym|b|bdo|big|cite|code|dfn|em|font|i|img|kbd|nobr|s|small|span|strike|strong|sub|sup|tt|";
static std::string empty_tags = "|area|base|basefont|bgsound|br|command|col|embed|event-source|frame|hr|image|img|input|keygen|link|menuitem|meta|param|source|spacer|track|wbr|";
@ -36,35 +38,27 @@ static void replace_all(std::string& s, const std::string& s1, const std::string
static std::wstring htmlToXhtml(std::string& sFileContent, bool bNeedConvert)
{
// Распознование кодировки
if (bNeedConvert)
{
size_t posEncoding = sFileContent.find("charset=");
if (posEncoding == std::string::npos)
posEncoding = sFileContent.find("encoding=");
if (posEncoding != std::string::npos)
{
posEncoding = sFileContent.find("=", posEncoding) + 1;
char quoteSymbol = '\"';
if(sFileContent[posEncoding] == '\"' || sFileContent[posEncoding] == '\'')
{
quoteSymbol = sFileContent[posEncoding];
posEncoding += 1;
}
{ // Определение кодировки
std::string sEncoding = NSStringFinder::FindPropety(sFileContent, "charset", {"="}, {";", "\\n", "\\r", " ", "\""});
size_t posEnd = sFileContent.find(quoteSymbol, posEncoding);
if (std::string::npos != posEnd)
{
std::string sEncoding = sFileContent.substr(posEncoding, posEnd - posEncoding);
if (sEncoding != "utf-8" && sEncoding != "UTF-8")
{
NSUnicodeConverter::CUnicodeConverter oConverter;
sFileContent = U_TO_UTF8(oConverter.toUnicode(sFileContent, sEncoding.c_str()));
}
}
if (sEncoding.empty())
sEncoding = NSStringFinder::FindPropety(sFileContent, "encoding", {"="}, {";", "\\n", "\\r", " "});
if (!sEncoding.empty() && !NSStringFinder::Equals("utf-8", sEncoding))
{
NSUnicodeConverter::CUnicodeConverter oConverter;
sFileContent = U_TO_UTF8(oConverter.toUnicode(sFileContent, sEncoding.c_str()));
}
}
// Избавляемся от лишних символов до <...
boost::regex oRegex("<[a-zA-Z]");
boost::match_results<typename std::string::const_iterator> oResult;
if (boost::regex_search(sFileContent, oResult, oRegex))
sFileContent.erase(0, oResult.position());
// Избавление от <a/>
size_t posA = sFileContent.find("<a ");
while(posA != std::string::npos)
@ -120,7 +114,7 @@ static std::string Base64ToString(const std::string& sContent, const std::string
if (TRUE == NSBase64::Base64Decode(sContent.c_str(), nSrcLen, pData, &nDecodeLen))
{
std::wstring sConvert;
if(!sCharset.empty() && sCharset != "utf-8" && sCharset != "UTF-8")
if(!sCharset.empty() && NSStringFinder::Equals<std::string>("utf-8", sCharset))
{
NSUnicodeConverter::CUnicodeConverter oConverter;
sConvert = oConverter.toUnicode(reinterpret_cast<char *>(pData), (unsigned)nDecodeLen, sCharset.data());
@ -208,8 +202,8 @@ static std::string QuotedPrintableDecode(const std::string& sContent, std::strin
return sRes.GetData();
}
static void ReadMht(std::string& sFileContent, size_t& nFound, size_t& nNextFound, const std::string& sBoundary,
std::map<std::string, std::string>& sRes, NSStringUtils::CStringBuilderA& oRes)
static void ReadMht(std::string& sFileContent, size_t& nFound, size_t& nNextFound,
std::map<std::string, std::string>& sRes, NSStringUtils::CStringBuilderA& oRes)
{
// Content
size_t nContentTag = sFileContent.find("\n\n", nFound);
@ -234,90 +228,50 @@ static void ReadMht(std::string& sFileContent, size_t& nFound, size_t& nNextFoun
nContentTag += 2;
// Content-Type
size_t nTag = sFileContent.find("Content-Type: ", nFound);
if(nTag == std::string::npos || nTag > nContentTag)
std::string sContentType = NSStringFinder::FindPropety(sFileContent, "content-type", {":"}, {";", "\\n", "\\r"}, nFound);
if (sContentType.empty())
{
nFound = nNextFound;
return;
}
size_t nTagEnd = sFileContent.find_first_of(";\n\r", nTag);
nTag += 14;
if(nTagEnd == std::string::npos || nTagEnd > nContentTag)
{
nFound = nNextFound;
return;
}
std::string sContentType = sFileContent.substr(nTag, nTagEnd - nTag);
if(sContentType == "multipart/alternative")
if (NSStringFinder::Equals(sContentType, std::string("multipart/alternative")))
nContentTag = nFound;
size_t nTag = 0, nTagEnd = 0;
// name
std::string sName;
nTag = sFileContent.find(" name=", nFound);
if(nTag != std::string::npos && nTag < nContentTag)
{
nTagEnd = sFileContent.find_first_of(";\n\r", nTag);
nTag += 6;
if(nTagEnd != std::string::npos && nTagEnd < nContentTag)
sName = sFileContent.substr(nTag, nTagEnd - nTag);
}
std::string sName = NSStringFinder::FindPropety(sFileContent, "name", {"="}, {";", "\\n", "\\r"}, nFound);
// charset
std::string sCharset;
nTag = sFileContent.find("charset=", nFound);
if(nTag != std::string::npos && nTag < nContentTag)
{
nTagEnd = sFileContent.find_first_of(";\n\r", nTag);
nTag += 8;
if(nTagEnd != std::string::npos && nTagEnd < nContentTag)
{
if(sFileContent[nTag] == '\"')
{
nTag++;
nTagEnd--;
}
sCharset = sFileContent.substr(nTag, nTagEnd - nTag);
}
}
std::string sCharset = NSStringFinder::FindPropety(sFileContent, "charset", {"="}, {";", "\\n", "\\r"}, nFound);
NSStringFinder::CutInside<std::string>(sCharset, "\"");
// Content-Location
std::string sContentLocation;
nTag = sFileContent.find("Content-Location: ", nFound);
if(nTag != std::string::npos && nTag < nContentTag)
{
nTagEnd = sFileContent.find_first_of(";\n\r", nTag);
nTag += 18;
if(nTagEnd != std::string::npos && nTagEnd < nContentTag)
sContentLocation = sFileContent.substr(nTag, nTagEnd - nTag);
}
std::string sContentLocation = NSStringFinder::FindPropety(sFileContent, "content-location", {":"}, {";", "\\n", "\\r"}, nFound);
if (sContentLocation.empty())
{
// Content-ID
std::string sContentID;
nTag = sFileContent.find("Content-ID: <", nFound);
if(nTag != std::string::npos && nTag < nContentTag)
{
nTagEnd = sFileContent.find_first_of(">", nTag);
nTag += 13;
if(nTagEnd != std::string::npos && nTagEnd < nContentTag)
sContentID = sFileContent.substr(nTag, nTagEnd - nTag);
}
std::string sContentID = NSStringFinder::FindPropety(sFileContent, "content-id", {":"}, {";", "\\n", "\\r"}, nFound);
NSStringFinder::CutInside<std::string>(sCharset, "<", ">");
if (!sContentID.empty())
sContentLocation = "cid:" + sContentID;
}
// Content-Transfer-Encoding
std::string sContentEncoding;
nTag = sFileContent.find("Content-Transfer-Encoding: ", nFound);
if(nTag != std::string::npos && nTag < nContentTag)
{
nTagEnd = sFileContent.find_first_of(";\n\r", nTag);
nTag += 27;
if(nTagEnd != std::string::npos && nTagEnd < nContentTag)
sContentEncoding = sFileContent.substr(nTag, nTagEnd - nTag);
}
std::string sContentEncoding = NSStringFinder::FindPropety(sFileContent, "content-transfer-encoding", {":"}, {";", "\\n", "\\r"}, nFound);;
// nTag = sFileContent.find("Content-Transfer-Encoding: ", nFound);
// if(nTag != std::string::npos && nTag < nContentTag)
// {
// nTagEnd = sFileContent.find_first_of(";\n\r", nTag);
// nTag += 27;
// if(nTagEnd != std::string::npos && nTagEnd < nContentTag)
// sContentEncoding = sFileContent.substr(nTag, nTagEnd - nTag);
// }
// Content
nTagEnd = nNextFound - 2;
@ -328,53 +282,52 @@ static void ReadMht(std::string& sFileContent, size_t& nFound, size_t& nNextFoun
}
std::string sContent = sFileContent.substr(nContentTag, nTagEnd - nContentTag);
// Удаляем лишнее
sFileContent.erase(0, nNextFound);
nFound = sFileContent.find(sBoundary);
std::wstring sExtention = NSFile::GetFileExtention(UTF8_TO_U(sName));
std::transform(sExtention.begin(), sExtention.end(), sExtention.begin(), tolower);
// std::transform(sExtention.begin(), sExtention.end(), sExtention.begin(), tolower);
// Основной документ
if(sContentType == "multipart/alternative")
if (NSStringFinder::Equals(sContentType, "multipart/alternative"))
oRes.WriteString(mhtTohtml(sContent));
else if((sContentType.find("text") != std::string::npos && (sExtention.empty() || sExtention == L"htm" || sExtention == L"html" || sExtention
== L"xhtml" || sExtention == L"css")) || (sContentType == "application/octet-stream" && (sContentLocation.find("css") !=
std::string::npos)))
else if ((NSStringFinder::Find(sContentType, "text") && (sExtention.empty() || NSStringFinder::EqualOf(sExtention, {L"htm", L"html", L"xhtml", L"css"})))
|| (NSStringFinder::Equals(sContentType, "application/octet-stream") && NSStringFinder::Find(sContentLocation, "css")))
{
// Стили заключаются в тэг <style>
if(sContentType == "text/css" || sExtention == L"css" || sContentLocation.find("css") != std::string::npos)
const bool bAddTagStyle = NSStringFinder::Equals(sContentType, "text/css") || NSStringFinder::Equals(sExtention, L"css") || NSStringFinder::Find(sContentLocation, "css");
if (bAddTagStyle)
oRes.WriteString("<style>");
if(sContentEncoding == "Base64" || sContentEncoding == "base64")
if (NSStringFinder::Equals(sContentEncoding, "base64"))
oRes.WriteString(Base64ToString(sContent, sCharset));
else if(sContentEncoding == "8bit" || sContentEncoding == "7bit" || sContentEncoding.empty())
else if (NSStringFinder::EqualOf(sContentEncoding, {"8bit", "7bit"}) || sContentEncoding.empty())
{
if (sCharset != "utf-8" && sCharset != "UTF-8" && !sCharset.empty())
if (!NSStringFinder::Equals(sCharset, "utf-8") && !sCharset.empty())
{
NSUnicodeConverter::CUnicodeConverter oConverter;
sContent = U_TO_UTF8(oConverter.toUnicode(sContent, sCharset.data()));
}
oRes.WriteString(sContent);
}
else if(sContentEncoding == "quoted-printable" || sContentEncoding == "Quoted-Printable")
else if (NSStringFinder::Equals(sContentEncoding, "quoted-printable"))
{
sContent = QuotedPrintableDecode(sContent, sCharset);
if (sCharset != "utf-8" && sCharset != "UTF-8" && !sCharset.empty())
if (!NSStringFinder::Equals(sCharset, "utf-8") && !sCharset.empty())
{
NSUnicodeConverter::CUnicodeConverter oConverter;
sContent = U_TO_UTF8(oConverter.toUnicode(sContent, sCharset.data()));
}
oRes.WriteString(sContent);
}
if(sContentType == "text/css" || sExtention == L"css" || sContentLocation.find("css") != std::string::npos)
if(bAddTagStyle)
oRes.WriteString("</style>");
}
// Картинки
else if((sContentType.find("image") != std::string::npos || sExtention == L"gif" || sContentType == "application/octet-stream") &&
(sContentEncoding == "Base64" || sContentEncoding == "base64"))
else if ((NSStringFinder::Find(sContentType, "image") || NSStringFinder::Equals(sExtention, L"gif") || NSStringFinder::Equals(sContentType, "application/octet-stream")) &&
NSStringFinder::Equals(sContentEncoding, "base64"))
{
if(sExtention == L"ico" || sContentType.find("ico") != std::string::npos)
if (NSStringFinder::Equals(sExtention, L"ico") || NSStringFinder::Find(sContentType, "ico"))
sContentType = "image/jpg";
else if(sExtention == L"gif")
else if(NSStringFinder::Equals(sExtention, L"gif"))
sContentType = "image/gif";
int nSrcLen = (int)sContent.length();
int nDecodeLen = NSBase64::Base64DecodeGetRequiredLength(nSrcLen);
@ -390,45 +343,39 @@ static std::string mhtTohtml(std::string& sFileContent)
std::map<std::string, std::string> sRes;
NSStringUtils::CStringBuilderA oRes;
size_t nFound = 0;
// Поиск boundary
size_t nFound = sFileContent.find("boundary=");
if(nFound == std::string::npos)
std::string sBoundary = NSStringFinder::FindPropety(sFileContent, "boundary", {"="}, {"\\r", "\\n", "\""}, 0, nFound);
if (sBoundary.empty())
{
size_t nFoundEnd = sFileContent.length();
nFound = 0;
ReadMht(sFileContent, nFound, nFoundEnd, "no", sRes, oRes);
ReadMht(sFileContent, nFound, nFoundEnd, sRes, oRes);
return oRes.GetData();
}
size_t nFoundEnd = sFileContent.find_first_of(";\n\r", nFound);
if(nFoundEnd == std::string::npos)
return "";
nFound += 9;
if(sFileContent[nFound] == '\"')
{
nFound++;
nFoundEnd--;
}
if(nFound > nFoundEnd)
return "";
std::string sBoundary = sFileContent.substr(nFound, nFoundEnd - nFound);
NSStringFinder::CutInside<std::string>(sBoundary, "\"");
size_t nFoundEnd{nFound};
sBoundary = "--" + sBoundary;
size_t nBoundaryLength = sBoundary.length();
// Удаляем лишнее
nFound = sFileContent.find(sBoundary, nFoundEnd);
sFileContent.erase(0, nFound);
nFound = sFileContent.find(sBoundary, nFound) + nBoundaryLength;
// Цикл по boundary
nFound = 0;
while(nFound != std::string::npos)
{
// Выход по --boundary--
if(sFileContent[nFound + nBoundaryLength + 1] == '-')
break;
nFoundEnd = sFileContent.find(sBoundary, nFound + nBoundaryLength);
if(nFoundEnd == std::string::npos)
break;
ReadMht(sFileContent, nFound, nFoundEnd, sBoundary, sRes, oRes);
ReadMht(sFileContent, nFound, nFoundEnd, sRes, oRes);
nFound = sFileContent.find(sBoundary, nFoundEnd + nBoundaryLength);;
}
std::string sFile = oRes.GetData();
for(const std::pair<std::string, std::string>& item : sRes)
{

View File

@ -20,6 +20,12 @@ bool CSvgFile::ReadFromBuffer(BYTE *pBuffer, unsigned int unSize)
return false;
}
bool CSvgFile::ReadFromWString(const std::wstring &wsContext)
{
Clear();
return m_oParser.LoadFromString(wsContext, &m_oContainer, this);
}
bool CSvgFile::OpenFromFile(const std::wstring &wsFile)
{
Clear();
@ -38,13 +44,34 @@ bool CSvgFile::GetBounds(double &dX, double &dY, double &dWidth, double &dHeight
dX = oWindow.m_oX .ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH);
dY = oWindow.m_oY .ToDouble(NSCSS::Pixel, SVG_FILE_HEIGHT);
dWidth = oWindow.m_oWidth .ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH);
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, SVG_FILE_HEIGHT);
if (SVG::Equals(0., dWidth))
dWidth = (!m_oContainer.GetViewBox().m_oWidth.Empty()) ? m_oContainer.GetViewBox().m_oWidth.ToDouble(NSCSS::Pixel) : SVG_FILE_WIDTH;
if (SVG::Equals(0., dHeight))
dHeight = (!m_oContainer.GetViewBox().m_oHeight.Empty()) ? m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel) : SVG_FILE_HEIGHT;
dWidth = 0.;
dHeight = 0.;
if (!oWindow.m_oWidth.Empty() && !oWindow.m_oWidth.Zero())
{
if (NSCSS::Percent != oWindow.m_oWidth.GetUnitMeasure() && !m_oContainer.GetViewBox().m_oWidth.Empty() && !m_oContainer.GetViewBox().m_oWidth.Zero())
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, m_oContainer.GetViewBox().m_oWidth.ToDouble(NSCSS::Pixel));
else
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel);
}
else if (!m_oContainer.GetViewBox().m_oWidth.Empty() && !m_oContainer.GetViewBox().m_oWidth.Zero())
dWidth = m_oContainer.GetViewBox().m_oWidth.ToDouble(NSCSS::Pixel);
if (!oWindow.m_oHeight.Empty() && !oWindow.m_oHeight.Zero())
{
if (NSCSS::Percent != oWindow.m_oHeight.GetUnitMeasure() && !m_oContainer.GetViewBox().m_oHeight.Empty() && !m_oContainer.GetViewBox().m_oHeight.Zero())
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel));
else
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel);
}
else if (!m_oContainer.GetViewBox().m_oHeight.Empty() && !m_oContainer.GetViewBox().m_oHeight.Zero())
dHeight = m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel);
if (0. == dWidth)
dWidth = SVG_FILE_WIDTH;
if (0. == dHeight)
dHeight = SVG_FILE_HEIGHT;
return true;
}
@ -59,6 +86,11 @@ void CSvgFile::SetFontManager(NSFonts::IFontManager *pFontManager)
m_oParser.SetFontManager(pFontManager);
}
void CSvgFile::SetWorkingDirectory(const std::wstring &wsWorkingDirectory)
{
m_wsWorkingDirectory = wsWorkingDirectory;
}
bool CSvgFile::MarkObject(SVG::CObject *pObject)
{
if (NULL == pObject || pObject->GetId().empty())
@ -146,21 +178,15 @@ bool CSvgFile::Draw(IRenderer *pRenderer, double dX, double dY, double dWidth, d
pRenderer->GetTransform(&oldTransform[0], &oldTransform[1], &oldTransform[2], &oldTransform[3], &oldTransform[4], &oldTransform[5]);
pRenderer->ResetTransform();
double dM11 = 1;
double dM22 = 1;
if (!oWindow.m_oWidth.Empty() && !oWindow.m_oWidth.Zero())
dM11 = dWidth / dWindowWidth;
if (!oWindow.m_oHeight.Empty() && !oWindow.m_oHeight.Zero())
dM22 = dHeight / dWindowHeight;
double dM11 = dWidth / dWindowWidth;
double dM22 = dHeight / dWindowHeight;
double dScaleX = 1, dScaleY = 1;
if (!oWindow.m_oWidth.Empty() && !oWindow.m_oWidth.Zero() && !oViewBox.m_oWidth.Empty() && !oViewBox.m_oWidth.Zero())
if (!SVG::Equals(0., dViewBoxWidth))
dScaleX = dWindowWidth / dViewBoxWidth;
if (!oWindow.m_oHeight.Empty() && !oWindow.m_oHeight.Zero() && !oViewBox.m_oHeight.Empty() && !oViewBox.m_oHeight.Zero())
if (!SVG::Equals(0., dViewBoxHeight))
dScaleY = dWindowHeight / dViewBoxHeight;
double dMinScale = std::min(dScaleX, dScaleY);

View File

@ -7,19 +7,23 @@
#include "CSvgParser.h"
#include "SvgObjects/CStyle.h"
class CSvgFile
#define SVG_DECL_IMPORT Q_DECL_IMPORT
class SVG_DECL_IMPORT CSvgFile
{
public:
CSvgFile();
~CSvgFile();
bool ReadFromBuffer(BYTE* pBuffer, unsigned int unSize);
bool ReadFromWString(const std::wstring& wsContext);
bool OpenFromFile(const std::wstring& wsFile);
bool GetBounds(double& dX, double& dY, double& dWidth, double& dHeight) const;
const SVG::CSvgCalculator* GetSvgCalculator() const;
void SetFontManager(NSFonts::IFontManager* pFontManager);
void SetWorkingDirectory(const std::wstring& wsWorkingDirectory);
bool MarkObject(SVG::CObject* pObject);
SVG::CObject* GetMarkedObject(const std::wstring& wsId) const;

View File

@ -1,7 +1,6 @@
#ifndef CSVGPARSER_H
#define CSVGPARSER_H
#include "../../graphics/pro/Fonts.h"
#include "../../../common/Directory.h"
#include "../../../xml/include/xmlutils.h"

View File

@ -59,21 +59,23 @@ namespace SVG
NSBase64::Base64Decode(wsImageData.c_str(), wsImageData.length(), pBuffer, &(int&)ulSize);
}
#ifndef METAFILE_DISABLE_FILESYSTEM
std::wstring wsFilePath = NSSystemPath::ShortenPath(m_wsHref);
else
{
std::wstring wsFilePath = NSSystemPath::ShortenPath(m_wsHref);
bool bIsAllowExternalLocalFiles = true;
if (NSProcessEnv::IsPresent(NSProcessEnv::Converter::gc_allowPrivateIP))
bIsAllowExternalLocalFiles = NSProcessEnv::GetBoolValue(NSProcessEnv::Converter::gc_allowPrivateIP);
bool bIsAllowExternalLocalFiles = true;
if (NSProcessEnv::IsPresent(NSProcessEnv::Converter::gc_allowPrivateIP))
bIsAllowExternalLocalFiles = NSProcessEnv::GetBoolValue(NSProcessEnv::Converter::gc_allowPrivateIP);
if (!bIsAllowExternalLocalFiles && wsFilePath.length() >= 3 && L"../" == wsFilePath.substr(0, 3))
return true;
wsFilePath = pFile->GetWorkingDirectory() + L'/' + wsFilePath;
if (!NSFile::CFileBinary::Exists(wsFilePath) || !NSFile::CFileBinary::ReadAllBytes(wsFilePath, &pBuffer, ulSize))
return false;
if (!bIsAllowExternalLocalFiles && wsFilePath.length() >= 3 && L"../" == wsFilePath.substr(0, 3))
return false;
wsFilePath = pFile->GetWorkingDirectory() + L'/' + wsFilePath;
if (!NSFile::CFileBinary::Exists(wsFilePath) || !NSFile::CFileBinary::ReadAllBytes(wsFilePath, &pBuffer, ulSize))
return false;
}
#endif
if (NULL == pBuffer)

View File

@ -10,6 +10,7 @@ CONFIG += plugin
DEFINES += HTMLFILE2_USE_DYNAMIC_LIBRARY
DEFINES += CSSCALCULATOR_LIBRARY_STATIC
DEFINES += CSS_CALCULATOR_WITH_XHTML
CORE_ROOT_DIR = $$PWD/..
PWD_ROOT_DIR = $$PWD
@ -29,4 +30,5 @@ ADD_DEPENDENCY(kernel, UnicodeConverter, graphics, kernel_network)
SOURCES += htmlfile2.cpp
HEADERS += htmlfile2.h
HEADERS += htmlfile2.h \
./src/StringFinder.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
#ifndef STRINGFINDER_H
#define STRINGFINDER_H
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include <vector>
#if defined(_WIN32) || defined (_WIN64)
#include <tchar.h>
#elif __linux__ || MAC
#include <libgen.h>
#endif
namespace NSStringFinder
{
template<class CharType, class StringType = std::basic_string<CharType, std::char_traits<CharType>, std::allocator<CharType>>>
StringType FindPropetyTemplate(const StringType& sString, const StringType& sProperty, const StringType& sDelimiter, const StringType& sEnding, const size_t& unStarting, size_t& unEndPosition)
{
if (sString.length() < unStarting)
return StringType();
typedef const boost::iterator_range<typename StringType::const_iterator> StringRange;
StringRange itFound = boost::algorithm::ifind_first(StringRange(sString.begin() + unStarting, sString.end()), sProperty);
if (itFound.empty())
return StringType();
StringRange itFoundBegin = boost::algorithm::ifind_first(StringRange(itFound.end(), sString.end()), sDelimiter);
if (itFoundBegin.empty())
return StringType();
StringRange itFoundEnd = boost::algorithm::ifind_first(StringRange(itFoundBegin.end(), sString.end()), sEnding);
if (itFoundEnd.empty())
return StringType();
unEndPosition += (itFoundEnd.end() - sString.begin());
StringType sValue{itFoundBegin.end(), itFoundEnd.begin()};
boost::algorithm::trim(sValue);
return sValue;
}
std::string FindPropety(const std::string& sString, const std::string& sProperty, const std::string& sDelimiter, const std::string& sEnding, const size_t& unStarting, size_t& unEndPosition)
{
return FindPropetyTemplate<char>(sString, sProperty, sDelimiter, sEnding, unStarting, unEndPosition);
}
std::wstring FindPropety(const std::wstring& wsString, const std::wstring& wsProperty, const std::wstring& wsDelimiter, const std::wstring& wsEnding, const size_t& unStarting, size_t& unEndPosition)
{
return FindPropetyTemplate<wchar_t>(wsString, wsProperty, wsDelimiter, wsEnding, unStarting, unEndPosition);
}
std::string FindPropety(const std::string& sString, const std::string& sProperty, const std::string& sDelimiter, const std::string& sEnding, const size_t& unStarting = 0)
{
size_t unEndPosition = 0;
return FindPropetyTemplate<char>(sString, sProperty, sDelimiter, sEnding, unStarting, unEndPosition);
}
std::wstring FindPropety(const std::wstring& wsString, const std::wstring& wsProperty, const std::wstring& wsDelimiter, const std::wstring& wsEnding, const size_t& unStarting = 0)
{
size_t unEndPosition = 0;
return FindPropetyTemplate<wchar_t>(wsString, wsProperty, wsDelimiter, wsEnding, unStarting, unEndPosition);
}
template<class CharType, class StringType = std::basic_string<CharType, std::char_traits<CharType>, std::allocator<CharType>>>
StringType FindPropetyTemplate(const StringType& sString, const StringType& sProperty, const std::vector<StringType>& arDelimiters, const std::vector<StringType>& arEndings, const size_t& unStarting, size_t& unEndPosition)
{
if (sString.length() < unStarting)
return StringType();
std::string sRegexValue = "(?i)" + std::string(sProperty.begin(), sProperty.end());
if (!arDelimiters.empty())
{
sRegexValue += "\\s*[";
for (const StringType& sDelimiter : arDelimiters)
sRegexValue += std::string(sDelimiter.begin(), sDelimiter.end()) + "|";
sRegexValue.pop_back();
sRegexValue += "]{1}";
}
if (!arEndings.empty())
{
std::string sEndingValue;
for (const StringType& sEnding : arEndings)
sEndingValue += std::string(sEnding.begin(), sEnding.end()) + "|";
sEndingValue.pop_back();
sRegexValue += "\\s*(.[^" + sEndingValue + "]*)\\s*[" + sEndingValue + "]?";
}
else
sRegexValue += "\\s*(.*)[\\n|\\r]?";
boost::regex oRegex(sRegexValue);
boost::match_results<typename StringType::const_iterator> oResult;
if (!boost::regex_search(sString.begin() + unStarting, sString.end(), oResult, oRegex))
return StringType();
unEndPosition = unStarting + oResult.position() + oResult.length();
StringType sValue(oResult[1]);
boost::algorithm::trim(sValue);
return sValue;
}
std::string FindPropety(const std::string& sString, const std::string& sProperty, const std::vector<std::string>& arDelimiters, const std::vector<std::string>& arEndings, const size_t& unStarting, size_t& unEndPosition)
{
return FindPropetyTemplate<char>(sString, sProperty, arDelimiters, arEndings, unStarting, unEndPosition);
}
std::wstring FindPropety(const std::wstring& wsString, const std::wstring& wsProperty, const std::vector<std::wstring>& arDelimiters, const std::vector<std::wstring>& arEndings, const size_t& unStarting, size_t& unEndPosition)
{
return FindPropetyTemplate<wchar_t>(wsString, wsProperty, arDelimiters, arEndings, unStarting, unEndPosition);
}
std::string FindPropety(const std::string& sString, const std::string& sProperty, const std::vector<std::string>& arDelimiters, const std::vector<std::string>& arEndings, const size_t& unStarting = 0)
{
size_t unEndPosition = 0;
return FindPropetyTemplate<char>(sString, sProperty, arDelimiters, arEndings, unStarting, unEndPosition);
}
std::wstring FindPropety(const std::wstring& wsString, const std::wstring& wsProperty, const std::vector<std::wstring>& arDelimiters, const std::vector<std::wstring>& arEndings, const size_t& unStarting = 0)
{
size_t unEndPosition = 0;
return FindPropetyTemplate<wchar_t>(wsString, wsProperty, arDelimiters, arEndings, unStarting, unEndPosition);
}
template <typename StringType, typename StringEndgeType>
void CutInside(StringType& sString, const StringEndgeType& sLeftEdge, const StringEndgeType& sRightEdge)
{
typedef const boost::iterator_range<typename StringType::const_iterator> StringRange;
StringRange itFoundBegin = boost::algorithm::ifind_first(StringRange(sString.begin(), sString.end()), sLeftEdge);
if (itFoundBegin.empty())
return;
StringRange itFoundEnd = boost::algorithm::ifind_first(StringRange(itFoundBegin.end(), sString.cend()), sRightEdge);
if (itFoundEnd.empty())
{
sString = StringType{itFoundBegin.end(), sString.cend()};
return;
}
sString = StringType{itFoundBegin.end(), itFoundEnd.begin()};
}
template <typename StringType, typename StringEdgeType>
void CutInside(StringType& sString, const StringEdgeType& sEdge)
{
CutInside(sString, sEdge, sEdge);
}
template <typename StringFirstType, typename StringSecondType>
bool Equals(const StringFirstType& sFirstString, const StringSecondType& sSecondString)
{
return boost::iequals(sFirstString, sSecondString);
}
template <typename StringFirstType, typename StringSecondType>
bool EqualOf(const StringFirstType& sFirstString, const std::vector<StringSecondType>& arStrings)
{
for (const StringFirstType& sString : arStrings)
if (boost::iequals(sFirstString, sString))
return true;
return false;
}
template <typename StringFirstType, typename StringSecondType>
bool EqualOf(const StringFirstType& sFirstString, const std::initializer_list<StringSecondType>& arStrings)
{
for (const StringFirstType& sString : arStrings)
if (boost::iequals(sFirstString, sString))
return true;
return false;
}
template <typename StringType, typename StringValueType>
bool Find(const StringType& sString, const StringValueType& sValue)
{
return !boost::algorithm::ifind_first(sString, sValue).empty();
}
int ToInt(const std::wstring& oValue, int nMinValue = 0)
{
boost::wregex oRegex(LR"((-?\.\d+|-?\d+(\.\d+)?))");
boost::match_results<typename std::wstring::const_iterator> oResult;
if (!boost::regex_search(oValue.begin(), oValue.end(), oResult, oRegex))
return nMinValue;
const int nValue = std::stoi(*oResult.begin());
return std::max(nMinValue, nValue);
}
int ToDouble(const std::wstring& oValue, double dMinValue = 0.)
{
boost::wregex oRegex(LR"((-?\.\d+|-?\d+(\.\d+)?))");
boost::match_results<typename std::wstring::const_iterator> oResult;
if (!boost::regex_search(oValue.begin(), oValue.end(), oResult, oRegex))
return dMinValue;
const double dValue = std::stod(*oResult.begin());
return (dValue >= dMinValue) ? dValue : dMinValue;
}
}
#endif // STRINGFINDER_H