diff --git a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp
index 8c4170e1d7..77938ba688 100644
--- a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp
+++ b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp
@@ -528,6 +528,8 @@ namespace NSCSS
oStyle.m_oPadding.Clear();
}
+ oStyle.m_oBorder.Clear();
+
CCompiledStyle oTempStyle;
oTempStyle.AddStyle(arSelectors[i].m_mAttributes, i + 1);
diff --git a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
index 6d6f59a66a..816ca43c35 100644
--- a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
+++ b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
@@ -396,7 +396,27 @@ namespace NSCSS
std::wstring wsColor = oBorder.GetColor().ToWString();
std::wstring wsStyle = oBorder.GetStyle().ToWString();
- double dWidth = oBorder.GetWidth().ToDouble(Point) * 8; // Так как значение указано в восьмых долях точки
+
+ int nWidth = static_cast(std::round(oBorder.GetWidth().ToDouble(Point) * 8.));
+
+ 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";
@@ -404,7 +424,7 @@ namespace NSCSS
if (wsStyle.empty())
wsStyle = L"single";
- return L"w:val=\"" + wsStyle + L"\" w:sz=\"" + std::to_wstring(static_cast(dWidth)) + + L"\" w:space=\"0\" w:color=\"" + wsColor + L"\"";
+ return L"w:val=\"" + wsStyle + L"\" w:sz=\"" + std::to_wstring(nWidth) + + L"\" w:space=\"0\" w:color=\"" + wsColor + L"\"";
}
void CDocumentStyle::SetRStyle(const NSCSS::CCompiledStyle& oStyle, CXmlElement& oXmlElement)
diff --git a/HtmlFile2/htmlfile2.cpp b/HtmlFile2/htmlfile2.cpp
index 7ee9de6a5f..bdbfcad343 100644
--- a/HtmlFile2/htmlfile2.cpp
+++ b/HtmlFile2/htmlfile2.cpp
@@ -141,6 +141,22 @@ struct TTableStyles
}
};
+struct TTableRowStyle
+{
+ UINT m_unMaxIndex;
+ UINT m_unMaxHeight;
+ bool m_bIsHeader;
+
+ TTableRowStyle()
+ : m_unMaxIndex(0), m_unMaxHeight(0), m_bIsHeader(false)
+ {}
+
+ bool Empty() const
+ {
+ return 0 == m_unMaxHeight && false == m_bIsHeader;
+ }
+};
+
struct TTableCellStyle
{
NSCSS::NSProperties::CDigit m_oWidth;
@@ -151,7 +167,7 @@ struct TTableCellStyle
std::wstring m_wsAlign;
- TTableCellStyle() {}
+ TTableCellStyle(){}
bool Empty()
{
@@ -163,9 +179,37 @@ class CTableCell
{
public:
CTableCell()
- : m_unColspan(1), m_unRowSpan(1)
+ : m_unColspan(1), m_unRowSpan(1), m_bIsMerged(false)
{}
+ CTableCell(UINT unColspan, UINT unRowspan, bool bIsMerged)
+ : m_unColspan(unColspan), m_unRowSpan(unRowspan), m_bIsMerged(bIsMerged)
+ {}
+
+ CTableCell(CTableCell& oCell)
+ : m_unColspan(oCell.m_unColspan), m_unRowSpan(oCell.m_unRowSpan), m_bIsMerged(oCell.m_bIsMerged),
+ m_oStyles(oCell.m_oStyles)
+ {
+ m_oData.SetText(oCell.m_oData.GetData());
+ }
+
+ CTableCell* Copy()
+ {
+ return new CTableCell(*this);
+ }
+
+ static CTableCell* CreateEmpty(UINT unColspan = 1, bool m_bIsMerged = false, const TTableCellStyle* pStyle = NULL)
+ {
+ CTableCell *pCell = new CTableCell(unColspan, 1, m_bIsMerged);
+
+ if (NULL != pStyle)
+ pCell->m_oStyles = *pStyle;
+
+ pCell->m_oData.SetText(L"");
+
+ return pCell;
+ }
+
void SetColspan(UINT unColspan, UINT unCurrentIndex)
{
if (MAXCOLUMNSINTABLE - 1 != unCurrentIndex)
@@ -194,6 +238,11 @@ public:
return &m_oData;
}
+ const TTableCellStyle* GetStyles() const
+ {
+ return &m_oStyles;
+ }
+
void SetWidth(const NSCSS::NSProperties::CDigit& oWidth)
{
m_oStyles.m_oWidth = oWidth;
@@ -204,6 +253,11 @@ public:
m_oStyles.m_oHeight = oHeight;
}
+ UINT GetHeight() const
+ {
+ return m_oStyles.m_oHeight.ToInt(NSCSS::Twips, DEFAULT_PAGE_HEIGHT);
+ }
+
void SetBorder(const NSCSS::NSProperties::CBorder& oBorder)
{
m_oStyles.m_oBorder = oBorder;
@@ -224,61 +278,64 @@ public:
NSStringUtils::CStringBuilder oCell;
oCell.WriteNodeBegin(L"w:tc");
+ oCell.WriteNodeBegin(L"w:tcPr");
- if (!m_oStyles.Empty())
+ if (!m_oStyles.m_oWidth.Empty())
{
- oCell.WriteNodeBegin(L"w:tcPr");
-
- if (!m_oStyles.m_oWidth.Empty())
- {
- if (NSCSS::UnitMeasure::Percent == m_oStyles.m_oWidth.GetUnitMeasure())
- oCell += L"";
- else
- oCell += L"";
- }
+ if (NSCSS::UnitMeasure::Percent == m_oStyles.m_oWidth.GetUnitMeasure())
+ oCell += L"";
else
- oCell += L"";
-
- if (1 < m_unColspan)
- oCell += L"";
-
- if (!m_oStyles.m_oBorder.Zero() && !m_oStyles.m_oBorder.Empty())
- oCell += L"" + CreateBorders(m_oStyles.m_oBorder) + L"";
- else if (oTableStyles.m_bHaveBorderAttribute)
- oCell += L"";
-
- if (!m_oStyles.m_oBackground.Empty())
- {
- const std::wstring wsShdFill{(NSCSS::NSProperties::ColorNone == m_oStyles.m_oBackground.GetType()) ? L"auto" : m_oStyles.m_oBackground.ToWString()};
- oCell += L"";
- }
-
- if (!m_oStyles.m_wsAlign.empty())
- oCell += L"";
-
- if (!m_oStyles.m_oPadding.Empty() && oTableStyles.m_oPadding != m_oStyles.m_oPadding)
- {
- const int nTopPadding = std::max(oTableStyles.m_oPadding.GetTop() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT),
- m_oStyles .m_oPadding.GetTop() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT));
- const int nLeftPadding = std::max(oTableStyles.m_oPadding.GetLeft() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH),
- m_oStyles .m_oPadding.GetLeft() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH));
- const int nBottomPadding = std::max(oTableStyles.m_oPadding.GetBottom().ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT),
- m_oStyles .m_oPadding.GetBottom().ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT));
- const int nRightPadding = std::max(oTableStyles.m_oPadding.GetRight() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH),
- m_oStyles .m_oPadding.GetRight() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH));
-
- oCell += L""
- ""
- ""
- ""
- ""
- "";
- }
-
- oCell += L"";
- oCell.WriteNodeEnd(L"w:tcPr");
+ oCell += L"";
}
-
+ else
+ oCell += L"";
+
+ if (1 < m_unColspan)
+ oCell += L"";
+
+ if (m_bIsMerged)
+ oCell += L"";
+ else if (1 < m_unRowSpan)
+ oCell += L"";
+
+ if (!m_oStyles.m_oBorder.Zero() && !m_oStyles.m_oBorder.Empty())
+ oCell += L"" + CreateBorders(m_oStyles.m_oBorder) + L"";
+ else if (oTableStyles.m_bHaveBorderAttribute)
+ oCell += L"";
+
+ if (!m_oStyles.m_oBackground.Empty())
+ {
+ const std::wstring wsShdFill{(NSCSS::NSProperties::ColorNone == m_oStyles.m_oBackground.GetType()) ? L"auto" : m_oStyles.m_oBackground.ToWString()};
+ oCell += L"";
+ }
+
+ if (!m_oStyles.m_wsAlign.empty())
+ oCell += L"";
+ else
+ oCell += L"";
+
+ if (!m_oStyles.m_oPadding.Empty() && oTableStyles.m_oPadding != m_oStyles.m_oPadding)
+ {
+ const int nTopPadding = std::max(oTableStyles.m_oPadding.GetTop() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT),
+ m_oStyles .m_oPadding.GetTop() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT));
+ const int nLeftPadding = std::max(oTableStyles.m_oPadding.GetLeft() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH),
+ m_oStyles .m_oPadding.GetLeft() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH));
+ const int nBottomPadding = std::max(oTableStyles.m_oPadding.GetBottom().ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT),
+ m_oStyles .m_oPadding.GetBottom().ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_HEIGHT));
+ const int nRightPadding = std::max(oTableStyles.m_oPadding.GetRight() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH),
+ m_oStyles .m_oPadding.GetRight() .ToInt(NSCSS::UnitMeasure::Twips, DEFAULT_PAGE_WIDTH));
+
+ oCell += L""
+ ""
+ ""
+ ""
+ ""
+ "";
+ }
+
+ oCell += L"";
+ oCell.WriteNodeEnd(L"w:tcPr");
+
oCell += m_oData.GetData();
oCell.WriteNodeEnd(L"w:tc");
@@ -290,6 +347,8 @@ private:
UINT m_unColspan;
UINT m_unRowSpan;
+ bool m_bIsMerged;
+
TTableCellStyle m_oStyles;
NSStringUtils::CStringBuilder m_oData;
};
@@ -298,37 +357,56 @@ class CTableRow
{
public:
CTableRow()
- : m_unMaxIndex(0)
{}
~CTableRow()
{
for (CTableCell* pCell : m_arCells)
- delete pCell;
+ RELEASEOBJECT(pCell);
}
void AddCell(CTableCell* pCell)
+ {
+ InsertCell(pCell, -1);
+ }
+
+ void InsertCell(CTableCell *pCell, int nPosition)
{
if (NULL == pCell)
return;
- m_arCells.push_back(pCell);
- m_unMaxIndex += pCell->GetColspan();
+ if (nPosition < 0)
+ m_arCells.push_back(pCell);
+ else
+ m_arCells.insert(m_arCells.begin() + nPosition, pCell);
+
+ m_oStyles.m_unMaxIndex += pCell->GetColspan();
+
+ if (1 == pCell->GetColspan() && 1 == pCell->GetRowspan())
+ m_oStyles.m_unMaxHeight = std::max(m_oStyles.m_unMaxHeight, pCell->GetHeight());
}
UINT GetIndex() const
{
- return m_unMaxIndex;
+ return m_oStyles.m_unMaxIndex;
}
- UINT GetCountIndex() const
+ UINT GetCount() const
{
return m_arCells.size();
}
bool ColumnsOverflowing() const
{
- return MAXCOLUMNSINTABLE == m_unMaxIndex;
+ return MAXCOLUMNSINTABLE == m_oStyles.m_unMaxIndex;
+ }
+
+ void RecalculateMaxIndex()
+ {
+ m_oStyles.m_unMaxIndex = 0;
+
+ for (const CTableCell* pCell : m_arCells)
+ m_oStyles.m_unMaxIndex += pCell->GetColspan();
}
std::wstring ConvertToOOXML(const TTableStyles& oTableStyles)
@@ -339,6 +417,22 @@ public:
NSStringUtils::CStringBuilder oRow;
oRow.WriteNodeBegin(L"w:tr");
+ if (!m_oStyles.Empty() || 0 <= oTableStyles.m_nCellSpacing)
+ {
+ oRow.WriteNodeBegin(L"w:trPr");
+
+ if (m_oStyles.m_bIsHeader)
+ oRow += L"";
+
+ if (0 < m_oStyles.m_unMaxHeight)
+ oRow += L"";
+
+ if (0 <= oTableStyles.m_nCellSpacing)
+ oRow += L"";
+
+ oRow.WriteNodeEnd(L"w:trPr");
+ }
+
for (CTableCell* pCell : m_arCells)
oRow += pCell->ConvertToOOXML(oTableStyles);
@@ -346,8 +440,16 @@ public:
return oRow.GetData();
}
+
+ CTableCell* operator[](UINT unIndex)
+ {
+ if (unIndex >= m_arCells.size())
+ return NULL;
+
+ return m_arCells[unIndex];
+ }
private:
- UINT m_unMaxIndex;
+ TTableRowStyle m_oStyles;
std::vector m_arCells;
};
@@ -360,14 +462,22 @@ public:
~CTable()
{
for (CTableRow* pRow : m_arRows)
- delete pRow;
+ RELEASEOBJECT(pRow);
}
void AddRow(CTableRow* pRow)
{
if (NULL == pRow)
return;
-
+
+ for (UINT unIndex = 0; unIndex < pRow->GetCount(); ++unIndex)
+ {
+ if (unIndex >= m_arMinColspan.size())
+ m_arMinColspan.push_back((*pRow)[unIndex]->GetColspan());
+ else if ((*pRow)[unIndex]->GetColspan() < m_arMinColspan[unIndex])
+ m_arMinColspan[unIndex] = (*pRow)[unIndex]->GetColspan();
+ }
+
m_arRows.push_back(pRow);
}
@@ -411,9 +521,64 @@ public:
return m_oStyles.m_bHaveBorderAttribute;
}
+ void ApplyRowspan()
+ {
+ CTableCell* pCell = NULL;
+ for (UINT unRowIndex = 0; unRowIndex < m_arRows.size(); ++unRowIndex)
+ {
+ for (UINT unColumnIndex = 0; unColumnIndex < m_arRows[unRowIndex]->GetCount(); ++unColumnIndex)
+ {
+ pCell = (*m_arRows[unRowIndex])[unColumnIndex];
+
+ if (1 != pCell->GetRowspan())
+ {
+ for (UINT unIndex = unRowIndex + 1; unIndex < m_arRows.size(); ++unIndex)
+ (*m_arRows[unIndex]).InsertCell(CTableCell::CreateEmpty(pCell->GetColspan(), true, pCell->GetStyles()), unColumnIndex);
+ }
+ }
+ }
+ }
+
void Shorten()
{
-
+ UINT unIndex = 0;
+ CTableCell* pCell = NULL;
+
+ while (unIndex < m_arMinColspan.size())
+ {
+ for (CTableRow* pRow : m_arRows)
+ {
+ pCell = (*pRow)[unIndex];
+
+ if (NULL == pCell)
+ continue;
+
+ if ((*pRow)[unIndex]->GetColspan() == m_arMinColspan[unIndex] + 1)
+ (*pRow)[unIndex]->SetColspan(2, MAXCOLUMNSINTABLE);
+ else if ((*pRow)[unIndex]->GetColspan() > m_arMinColspan[unIndex])
+ (*pRow)[unIndex]->SetColspan((*pRow)[unIndex]->GetColspan() - m_arMinColspan[unIndex], MAXCOLUMNSINTABLE);
+ }
+
+ ++unIndex;
+ }
+ }
+
+ void CompleteTable()
+ {
+ UINT unMaxIndex = 0;
+
+ for (CTableRow* pRow : m_arRows)
+ {
+ pRow->RecalculateMaxIndex();
+
+ if (unMaxIndex > pRow->GetIndex())
+ {
+ for (UINT unIndex = 0; unIndex < unMaxIndex - pRow->GetIndex(); ++unIndex)
+ pRow->AddCell(CTableCell::CreateEmpty());
+ }
+
+ unMaxIndex = std::max(pRow->GetIndex(), unMaxIndex);
+ }
}
std::wstring ConvertToOOXML()
@@ -474,6 +639,7 @@ public:
}
private:
std::vector m_arRows;
+ std::vector m_arMinColspan;
TTableStyles m_oStyles;
};
@@ -2050,8 +2216,10 @@ private:
GetSubClass(pCell->GetData(), sSelectors);
+ std::vector arNewSelectors{(std::vector::const_iterator)std::find_if(sSelectors.begin(), sSelectors.end(), [](const NSCSS::CNode& oNode){ return L"table" == oNode.m_wsName; }), sSelectors.cend()};
+
NSCSS::CCompiledStyle oStyle;
- m_oStylesCalculator.GetCompiledStyle(oStyle, sSelectors);
+ m_oStylesCalculator.GetCompiledStyle(oStyle, arNewSelectors);
pCell->SetAlign(oStyle.m_oDisplay.GetHAlign().ToWString());
pCell->SetHeight(oStyle.m_oDisplay.GetHeight());
@@ -2195,7 +2363,9 @@ private:
sSelectors.pop_back();
}
+ oTable.ApplyRowspan();
oTable.Shorten();
+ oTable.CompleteTable();
oXml->WriteString(oTable.ConvertToOOXML());
}