Fix bugs in html to ooxml conversion

This commit is contained in:
Kirill Polyakov
2024-04-15 21:46:24 +03:00
parent 52a07814f4
commit ca179304c3
5 changed files with 86 additions and 47 deletions

View File

@ -70,7 +70,7 @@ namespace NSCSS
{L"deepskyblue", L"00BFFF"}, {L"dodgerblue", L"1E90FF"}, {L"cornflowerblue",L"6495ED"}, {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"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"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 */ /* White tones */
{L"white", L"FFFFFF"}, {L"snow", L"FFFAFA"}, {L"honeydew", L"F0FFF0"}, {L"white", L"FFFFFF"}, {L"snow", L"FFFAFA"}, {L"honeydew", L"F0FFF0"},
{L"mintcream", L"F5FFFA"}, {L"azure", L"F0FFFF"}, {L"aliceblue", L"F0F8FF"}, {L"mintcream", L"F5FFFA"}, {L"azure", L"F0FFFF"}, {L"aliceblue", L"F0F8FF"},

View File

@ -2300,9 +2300,7 @@ namespace NSCSS
CFont &CFont::operator+=(const CFont &oFont) CFont &CFont::operator+=(const CFont &oFont)
{ {
if (!oFont.m_oSize.Empty()) m_oSize += oFont.m_oSize;
m_oSize = oFont.m_oSize;
m_oLineHeight += oFont.m_oLineHeight; m_oLineHeight += oFont.m_oLineHeight;
m_oFamily += oFont.m_oFamily; m_oFamily += oFont.m_oFamily;
m_oStretch += oFont.m_oStretch; m_oStretch += oFont.m_oStretch;

View File

@ -272,8 +272,15 @@ namespace NSCSS
if (oStyle.Empty()) if (oStyle.Empty())
return; 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; std::wstring sInfValue;
sInfValue.reserve(64); sInfValue.reserve(64);
@ -317,10 +324,10 @@ namespace NSCSS
oXmlElement.AddPropertiesInP(PProperties::P_ContextualSpacing, L"true"); oXmlElement.AddPropertiesInP(PProperties::P_ContextualSpacing, L"true");
} }
if (!oStyle.m_oBackground.Empty() && !oStyle.HaveThisParent(L"table")) if (!oStyle.m_oBackground.Empty() && !bInTable)
oXmlElement.AddPropertiesInP(PProperties::P_Shd, oStyle.m_oBackground.IsNone() ? L"auto" : oStyle.m_oBackground.GetColor().ToWString()); oXmlElement.AddPropertiesInP(PProperties::P_Shd, oStyle.m_oBackground.IsNone() ? L"auto" : oStyle.m_oBackground.GetColor().ToWString());
if (!oStyle.m_oBorder.Empty() && !oStyle.HaveThisParent(L"table")) if (!oStyle.m_oBorder.Empty() && !bInTable)
{ {
if (oStyle.m_oBorder.EqualSides()) if (oStyle.m_oBorder.EqualSides())
{ {
@ -450,7 +457,7 @@ namespace NSCSS
oXmlElement.AddPropertiesInR(RProperties::R_Highlight, wsHighlight); oXmlElement.AddPropertiesInR(RProperties::R_Highlight, wsHighlight);
oXmlElement.AddPropertiesInR(RProperties::R_Color, oStyle.m_oText.GetColor().ToWString()); oXmlElement.AddPropertiesInR(RProperties::R_Color, oStyle.m_oText.GetColor().ToWString());
std::wstring wsFontFamily{oStyle.m_oFont.GetFamily().ToWString()}; std::wstring wsFontFamily{oStyle.m_oFont.GetFamily().ToWString()};
if (L"sans-serif" == wsFontFamily) if (L"sans-serif" == wsFontFamily)
@ -466,6 +473,8 @@ namespace NSCSS
bool CDocumentStyle::WriteRStyle(const NSCSS::CCompiledStyle& oStyle) bool CDocumentStyle::WriteRStyle(const NSCSS::CCompiledStyle& oStyle)
{ {
Clear();
if(oStyle.GetId().empty()) if(oStyle.GetId().empty())
{ {
m_sId = L"normal"; m_sId = L"normal";
@ -479,7 +488,7 @@ namespace NSCSS
if (oItem != m_arStyleUsed.end()) if (oItem != m_arStyleUsed.end())
{ {
m_sId = (*oItem).getId(); m_sId = (*oItem).getId();
return false; return true;
} }
CXmlElement oXmlElement; CXmlElement oXmlElement;
@ -488,7 +497,6 @@ namespace NSCSS
if (oXmlElement.Empty()) if (oXmlElement.Empty())
return false; return false;
structStyle.setId(oXmlElement.GetStyleId());
m_arStyleUsed.push_back(structStyle); m_arStyleUsed.push_back(structStyle);
m_sStyle += oXmlElement.GetRStyle(); m_sStyle += oXmlElement.GetRStyle();

View File

@ -597,7 +597,7 @@ std::wstring CXmlElement::GetPStyle(bool bIsLite) const
{ {
if (bIsLite) if (bIsLite)
return ConvertPStyle(true); return ConvertPStyle(true);
return GetStyle(true, true, false); return GetStyle(true, true, false);
} }
@ -605,7 +605,7 @@ std::wstring CXmlElement::GetRStyle(bool bIsLite) const
{ {
if (bIsLite) if (bIsLite)
return ConvertRStyle(true); return ConvertRStyle(true);
return GetStyle(true, false, true); return GetStyle(true, false, true);
} }

View File

@ -174,13 +174,14 @@ struct TTableCellStyle
NSCSS::NSProperties::CIndent m_oPadding; NSCSS::NSProperties::CIndent m_oPadding;
NSCSS::NSProperties::CColor m_oBackground; NSCSS::NSProperties::CColor m_oBackground;
std::wstring m_wsAlign; std::wstring m_wsHAlign;
std::wstring m_wsVAlign;
TTableCellStyle(){} TTableCellStyle(){}
bool Empty() bool Empty()
{ {
return m_oWidth.Empty() && m_oHeight.Empty() && m_oBorder.Empty() && m_oPadding.Empty() && m_wsAlign.empty(); return m_oWidth.Empty() && m_oHeight.Empty() && m_oBorder.Empty() && m_oPadding.Empty() && m_wsVAlign.empty() && m_wsVAlign.empty();
} }
}; };
@ -282,9 +283,14 @@ public:
m_oStyles.m_oPadding = oPadding; m_oStyles.m_oPadding = oPadding;
} }
void SetAlign(const std::wstring& wsAlign) void SetHAlign(const std::wstring& wsAlign)
{ {
m_oStyles.m_wsAlign = wsAlign; m_oStyles.m_wsHAlign = wsAlign;
}
void SetVAlign(const std::wstring& wsAlign)
{
m_oStyles.m_wsVAlign = wsAlign;
} }
void SetBackground(const NSCSS::NSProperties::CColor& oColor) void SetBackground(const NSCSS::NSProperties::CColor& oColor)
@ -344,8 +350,8 @@ public:
oCell += L"<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"" + wsShdFill + L"\"/>"; oCell += L"<w:shd w:val=\"clear\" w:color=\"auto\" w:fill=\"" + wsShdFill + L"\"/>";
} }
if (!m_oStyles.m_wsAlign.empty()) if (!m_oStyles.m_wsVAlign.empty())
oCell += L"<w:vAlign w:val=\"" + m_oStyles.m_wsAlign + L"\"/>"; oCell += L"<w:vAlign w:val=\"" + m_oStyles.m_wsVAlign + L"\"/>";
else else
oCell += L"<w:vAlign w:val=\"center\"/>"; oCell += L"<w:vAlign w:val=\"center\"/>";
@ -463,7 +469,7 @@ public:
if (0 < m_oStyles.m_unMaxHeight) if (0 < m_oStyles.m_unMaxHeight)
oRow += L"<w:trHeight w:val=\"" + std::to_wstring(m_oStyles.m_unMaxHeight) + L"\"/>"; oRow += L"<w:trHeight w:val=\"" + std::to_wstring(m_oStyles.m_unMaxHeight) + L"\"/>";
if (0 <= oTableStyles.m_nCellSpacing) if (0 < oTableStyles.m_nCellSpacing)
oRow += L"<w:tblCellSpacing w:w=\"" + std::to_wstring(oTableStyles.m_nCellSpacing) + L"\" w:type=\"dxa\"/>"; oRow += L"<w:tblCellSpacing w:w=\"" + std::to_wstring(oTableStyles.m_nCellSpacing) + L"\" w:type=\"dxa\"/>";
oRow.WriteNodeEnd(L"w:trPr"); oRow.WriteNodeEnd(L"w:trPr");
@ -606,7 +612,7 @@ public:
if (1 != pCell->GetRowspan()) if (1 != pCell->GetRowspan())
{ {
for (UINT unIndex = unRowIndex + 1; unIndex < m_arRows.size(); ++unIndex) for (UINT unIndex = unRowIndex + 1; unIndex < std::min((UINT)m_arRows.size(), unRowIndex + pCell->GetRowspan()); ++unIndex)
(*m_arRows[unIndex]).InsertCell(CTableCell::CreateEmpty(pCell->GetColspan(), true, pCell->GetStyles()), unColumnIndex); (*m_arRows[unIndex]).InsertCell(CTableCell::CreateEmpty(pCell->GetColspan(), true, pCell->GetStyles()), unColumnIndex);
} }
} }
@ -618,16 +624,38 @@ public:
UINT unIndex = 0; UINT unIndex = 0;
CTableCell* pCell = NULL; CTableCell* pCell = NULL;
UINT unMaxIndex = 0; //Максимальный индекс без учета строк, где имеется только 1 ячейка
for (const CTableRow* pRow : m_arRows)
{
if (1 < pRow->GetCount())
unMaxIndex = std::max(unMaxIndex, pRow->GetIndex());
}
while (unIndex < m_arMinColspan.size()) while (unIndex < m_arMinColspan.size())
{ {
for (CTableRow* pRow : m_arRows) for (CTableRow* pRow : m_arRows)
{ {
if (0 != unMaxIndex && 1 == pRow->GetCount() && pRow->GetIndex() > unMaxIndex)
{
pCell = (*pRow)[unIndex];
if (NULL == pCell)
continue;
pCell->SetColspan(unMaxIndex , MAXCOLUMNSINTABLE);
continue;
}
if (1 == m_arMinColspan[unIndex])
break;
pCell = (*pRow)[unIndex]; pCell = (*pRow)[unIndex];
if (NULL == pCell) if (NULL == pCell)
continue; continue;
if (1 != pCell->GetColspan() && unIndex + pCell->GetColspan() > m_arMinColspan[unIndex]) if (1 < pCell->GetColspan() && unIndex + pCell->GetColspan() > m_arMinColspan[unIndex])
{ {
pCell->SetColspan(m_arMinColspan[unIndex] - unIndex, MAXCOLUMNSINTABLE); pCell->SetColspan(m_arMinColspan[unIndex] - unIndex, MAXCOLUMNSINTABLE);
continue; continue;
@ -695,7 +723,7 @@ public:
if (!m_oStyles.m_wsAlign.empty()) if (!m_oStyles.m_wsAlign.empty())
oTable += L"<w:jc w:val=\"" + m_oStyles.m_wsAlign + L"\"/>"; oTable += L"<w:jc w:val=\"" + m_oStyles.m_wsAlign + L"\"/>";
if (0 <= m_oStyles.m_nCellSpacing) if (0 < m_oStyles.m_nCellSpacing)
oTable += L"<w:tblCellSpacing w:w=\"" + std::to_wstring(m_oStyles.m_nCellSpacing) + L"\" w:type=\"dxa\"/>"; oTable += L"<w:tblCellSpacing w:w=\"" + std::to_wstring(m_oStyles.m_nCellSpacing) + L"\" w:type=\"dxa\"/>";
if (!m_oStyles.m_oBorder.Empty() && !m_oStyles.m_oBorder.Zero()) if (!m_oStyles.m_oBorder.Empty() && !m_oStyles.m_oBorder.Zero())
@ -724,9 +752,6 @@ public:
if (HaveCaption()) if (HaveCaption())
{ {
oTable.WriteNodeBegin(L"w:tr"); oTable.WriteNodeBegin(L"w:tr");
oTable.WriteNodeBegin(L"w:trPr");
oTable += L"<w:tblCellSpacing w:w=\"0\" w:type=\"dxa\"/>";
oTable.WriteNodeEnd(L"w:trPr");
oTable.WriteNodeBegin(L"w:tc"); oTable.WriteNodeBegin(L"w:tc");
oTable.WriteNodeBegin(L"w:tcPr"); oTable.WriteNodeBegin(L"w:tcPr");
oTable += L"<w:tcW w:w=\"0\" w:type=\"auto\"/>"; oTable += L"<w:tcW w:w=\"0\" w:type=\"auto\"/>";
@ -1597,6 +1622,7 @@ private:
if(sName == L"#text") if(sName == L"#text")
{ {
std::wstring sText = GetText(); std::wstring sText = GetText();
std::wstring wsTemp{sText};
size_t find = sText.find_first_not_of(L" \n\t\r"); size_t find = sText.find_first_not_of(L" \n\t\r");
if (find == std::wstring::npos) if (find == std::wstring::npos)
@ -1656,6 +1682,9 @@ private:
sText.erase(0, nAfter + 1); sText.erase(0, nAfter + 1);
nAfter = sText.find_first_of(L"\n\r"); nAfter = sText.find_first_of(L"\n\r");
} }
if (sText.empty())
return;
} }
else else
ReplaceSpaces(sText); ReplaceSpaces(sText);
@ -2007,7 +2036,7 @@ private:
// Таблицы // Таблицы
else if(sName == L"table") else if(sName == L"table")
ParseTable(oXml, sSelectors, oTS); ParseTable(oXml, sSelectors, oTS);
// Текст с границами // Текст с границами
else if(sName == L"textarea" || sName == L"fieldset") else if(sName == L"textarea" || sName == L"fieldset")
{ {
CTextSettings oTSP(oTS); CTextSettings oTSP(oTS);
@ -2032,12 +2061,20 @@ private:
sSelectors.pop_back(); sSelectors.pop_back();
} }
bool readStream (NSStringUtils::CStringBuilder* oXml, std::vector<NSCSS::CNode>& sSelectors, const CTextSettings& oTS) bool readStream (NSStringUtils::CStringBuilder* oXml, std::vector<NSCSS::CNode>& sSelectors, const CTextSettings& oTS, bool bInsertEmptyP = false)
{ {
int nDeath = m_oLightReader.GetDepth(); int nDeath = m_oLightReader.GetDepth();
if(m_oLightReader.IsEmptyNode() || !m_oLightReader.ReadNextSiblingNode2(nDeath)) if(m_oLightReader.IsEmptyNode() || !m_oLightReader.ReadNextSiblingNode2(nDeath))
{
if (bInsertEmptyP)
{
wrP(oXml, sSelectors, oTS);
wrR(oXml, sSelectors, oTS);
CloseP(oXml, sSelectors);
m_bInP = false;
}
return false; return false;
}
do do
{ {
readInside(oXml, sSelectors, oTS, m_oLightReader.GetName()); readInside(oXml, sSelectors, oTS, m_oLightReader.GetName());
@ -2055,7 +2092,8 @@ private:
NSCSS::CCompiledStyle oStyle; NSCSS::CCompiledStyle oStyle;
m_oStylesCalculator.GetCompiledStyle(oStyle, arNewSelectors); m_oStylesCalculator.GetCompiledStyle(oStyle, arNewSelectors);
pCell->SetAlign(oStyle.m_oDisplay.GetHAlign().ToWString()); pCell->SetVAlign(oStyle.m_oDisplay.GetVAlign().ToWString());
pCell->SetHAlign(oStyle.m_oDisplay.GetHAlign().ToWString());
pCell->SetBackground(oStyle.m_oBackground.GetColor()); pCell->SetBackground(oStyle.m_oBackground.GetColor());
pCell->SetHeight(oStyle.m_oDisplay.GetHeight()); pCell->SetHeight(oStyle.m_oDisplay.GetHeight());
pCell->SetWidth(oStyle.m_oDisplay.GetWidth()); pCell->SetWidth(oStyle.m_oDisplay.GetWidth());
@ -2119,21 +2157,16 @@ private:
if(m_oLightReader.GetName() == L"th") if(m_oLightReader.GetName() == L"th")
{ {
CTextSettings oTSR(oTS); CTextSettings oTSR(oTS);
oTSR.sPStyle += L"<w:jc w:val=\"center\"/>";
oTSR.sRStyle += L"<w:b/>"; if (pCell->GetStyles()->m_wsHAlign.empty())
readStream(pCell->GetData(), sSelectors, oTSR); oTSR.sPStyle += L"<w:jc w:val=\"center\"/>";
oTSR.sRStyle += L"<w:b/><w:bCs/>";
readStream(pCell->GetData(), sSelectors, oTSR, true);
} }
// Читаем td. Ячейка таблицы. Выравнивание вправо // Читаем td. Ячейка таблицы
else if(m_oLightReader.GetName() == L"td") else if(m_oLightReader.GetName() == L"td")
{ readStream(pCell->GetData(), sSelectors, oTS, true);
if (!readStream(pCell->GetData(), sSelectors, oTS))
{
wrP(pCell->GetData(), sSelectors, oTS);
wrR(pCell->GetData(), sSelectors, oTS);
CloseP(pCell->GetData(), sSelectors);
m_bInP = false;
}
}
if (pRow->ColumnsOverflowing()) if (pRow->ColumnsOverflowing())
{ {
@ -2142,10 +2175,10 @@ private:
oTrTS.bAddSpaces = true; oTrTS.bAddSpaces = true;
m_bWasSpace = true; m_bWasSpace = true;
while (m_oLightReader.ReadNextSiblingNode(nTrDepth) && L"td" == m_oLightReader.GetName()) while (m_oLightReader.ReadNextSiblingNode(nTrDepth) && (L"td" == m_oLightReader.GetName() || L"th" == m_oLightReader.GetName()))
{ {
GetSubClass(pCell->GetData(), sSelectors); GetSubClass(pCell->GetData(), sSelectors);
readStream(pCell->GetData(), sSelectors, oTrTS); readStream(pCell->GetData(), sSelectors, oTrTS, true);
sSelectors.pop_back(); sSelectors.pop_back();
} }
} }
@ -2184,7 +2217,7 @@ private:
oTable.HaveBorderAttribute(); oTable.HaveBorderAttribute();
} }
if (oXml->GetSubData(oXml->GetCurSize() - 8) == L"</w:tbl>") if (oXml->GetSubData(oXml->GetCurSize() - 8) == L"</w:tbl>")
WriteEmptyParagraph(oXml, true); WriteEmptyParagraph(oXml, true);
@ -2198,7 +2231,7 @@ private:
oTable.SetCellSpacing(NSStringFinder::ToInt(sSelectors.back().m_mAttributes[L"cellspacing"])); oTable.SetCellSpacing(NSStringFinder::ToInt(sSelectors.back().m_mAttributes[L"cellspacing"]));
else if (oStyle.m_oBorder.GetCollapse() == NSCSS::NSProperties::BorderCollapse::Separate) else if (oStyle.m_oBorder.GetCollapse() == NSCSS::NSProperties::BorderCollapse::Separate)
oTable.SetCellSpacing(15); oTable.SetCellSpacing(15);
oTable.SetWidth(oStyle.m_oDisplay.GetWidth()); oTable.SetWidth(oStyle.m_oDisplay.GetWidth());
oTable.SetBorder(oStyle.m_oBorder); oTable.SetBorder(oStyle.m_oBorder);
oTable.SetPadding(oStyle.m_oPadding); oTable.SetPadding(oStyle.m_oPadding);