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()); }