From 7c501fe5a3cd6173a3537d748f0458b0b9d82227 Mon Sep 17 00:00:00 2001 From: Kirill Polyakov Date: Mon, 3 Jun 2024 12:06:29 +0300 Subject: [PATCH] Fix bug #68252 --- .../html/css/src/CCssCalculator_Private.cpp | 10 +- .../3dParty/html/css/src/StyleProperties.cpp | 8 +- .../html/css/src/xhtml/CDocumentStyle.cpp | 13 +- .../html/css/src/xhtml/CXmlElement.cpp | 14 +-- HtmlFile2/htmlfile2.cpp | 116 +++++++++++------- 5 files changed, 96 insertions(+), 65 deletions(-) diff --git a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp index d4d6621dba..fd4852a583 100644 --- a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp +++ b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp @@ -510,22 +510,22 @@ namespace NSCSS std::vector arNodes = CalculateAllNodes(arSelectors); std::vector arPrevNodes; bool bInTable = false; - + for (size_t i = 0; i < arSelectors.size(); ++i) { oStyle.AddParent(arSelectors[i].m_wsName); // Скидываем некоторые внешние стили, которые внутри таблицы переопределяются if (L"table" == arSelectors[i].m_wsName) + bInTable = true; + + if (bInTable) { oStyle.m_oFont.GetLineHeight().Clear(); oStyle.m_oPadding.Clear(); oStyle.m_oMargin.Clear(); - bInTable = true; - } - - if (bInTable) oStyle.m_oBorder.Clear(); + } CCompiledStyle oTempStyle; diff --git a/Common/3dParty/html/css/src/StyleProperties.cpp b/Common/3dParty/html/css/src/StyleProperties.cpp index c380779c33..786f5e0957 100644 --- a/Common/3dParty/html/css/src/StyleProperties.cpp +++ b/Common/3dParty/html/css/src/StyleProperties.cpp @@ -2009,10 +2009,10 @@ namespace NSCSS CIndent &CIndent::operator+=(const CIndent &oIndent) { - m_oTop = oIndent.m_oTop; - m_oRight = oIndent.m_oRight; - m_oBottom = oIndent.m_oBottom; - m_oLeft = oIndent.m_oLeft; + if (!oIndent.m_oTop.Empty()) m_oTop = oIndent.m_oTop; + if (!oIndent.m_oRight.Empty()) m_oRight = oIndent.m_oRight; + if (!oIndent.m_oBottom.Empty()) m_oBottom = oIndent.m_oBottom; + if (!oIndent.m_oLeft.Empty()) m_oLeft = oIndent.m_oLeft; return *this; } diff --git a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp index 1c51ef9500..a326c97f39 100644 --- a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp +++ b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp @@ -11,6 +11,11 @@ #define DEFAULT_LINEHEIGHT 240 #define LINEHEIGHTSCALE 10 // Значение LineHeight в OOXML должно быть в 10 раз больше чем указано в стиле +#define VALUE_TO_INT(value, unit_measure) \ + (NSCSS::UnitMeasure::None != value.GetUnitMeasure()) ? \ + value.ToInt(unit_measure) : \ + static_cast(NSCSS::CUnitMeasureConverter::ConvertPx(value.ToDouble(), unit_measure, 96) + 0.5) + namespace NSCSS { CStyleUsed::CStyleUsed(const CCompiledStyle &oStyle, bool bIsPStyle) @@ -336,10 +341,12 @@ namespace NSCSS sSpacingValue.reserve(128); 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"\" "; + sSpacingValue += L"w:before=\"" + std::to_wstring(VALUE_TO_INT(oStyle.m_oMargin.GetTop(), NSCSS::Twips)) + L"\" w:beforeAutospacing=\"0\" "; 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"\" "; + sSpacingValue += L"w:after=\"" + std::to_wstring(VALUE_TO_INT(oStyle.m_oMargin.GetBottom(), NSCSS::Twips)) + L"\" w:afterAutospacing=\"0\" "; + else if (oStyle.m_oMargin.GetBottom().Zero() || bInTable) + sSpacingValue += L"w:after=\"0\" "; if (!oStyle.m_oFont.GetLineHeight().Empty() && !oStyle.m_oFont.GetLineHeight().Zero()) { @@ -348,6 +355,8 @@ namespace NSCSS sSpacingValue += L" w:line=\"" + wsLine + L"\" w:lineRule=\"" + wsLineRule + L"\""; } + else if (oStyle.m_oFont.GetLineHeight().Zero() || bInTable) + sSpacingValue += L"w:lineRule=\"auto\" w:line=\"240\""; if (!sSpacingValue.empty()) oXmlElement.AddPropertiesInP(PProperties::P_Spacing, sSpacingValue); diff --git a/Common/3dParty/html/css/src/xhtml/CXmlElement.cpp b/Common/3dParty/html/css/src/xhtml/CXmlElement.cpp index 199e1f2dd4..cd997a203e 100644 --- a/Common/3dParty/html/css/src/xhtml/CXmlElement.cpp +++ b/Common/3dParty/html/css/src/xhtml/CXmlElement.cpp @@ -45,7 +45,7 @@ void CXmlElement::CreateDefaultElement(const std::wstring& sNameDefaultElement) 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\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"li") { @@ -67,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:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"h2") { @@ -78,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:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"h3") { @@ -89,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:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"h4") { @@ -100,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:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"h5") { @@ -111,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:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"h6") @@ -123,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:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); +// AddPropertiesInP(CSSProperties::ParagraphProperties::P_Spacing, L"w:before=\"100\" w:beforeAutospacing=\"1\" w:after=\"100\" w:afterAutospacing=\"1\""); } else if (sNameDefaultElement == L"h1-c") { diff --git a/HtmlFile2/htmlfile2.cpp b/HtmlFile2/htmlfile2.cpp index 7186380400..090face832 100644 --- a/HtmlFile2/htmlfile2.cpp +++ b/HtmlFile2/htmlfile2.cpp @@ -174,6 +174,7 @@ typedef enum struct TTableStyles { NSCSS::NSProperties::CIndent m_oPadding; + NSCSS::NSProperties::CIndent m_oMargin; NSCSS::NSProperties::CBorder m_oBorder; NSCSS::NSProperties::CDigit m_oWidth; @@ -188,7 +189,7 @@ struct TTableStyles bool Empty() const { - return m_oPadding.Empty() && m_oBorder.Empty() && m_oWidth.Empty() && -1 == m_nCellSpacing && false == m_bHaveBorderAttribute && m_wsAlign.empty(); + return m_oPadding.Empty() && m_oMargin.Empty() && m_oBorder.Empty() && m_oWidth.Empty() && -1 == m_nCellSpacing && false == m_bHaveBorderAttribute && m_wsAlign.empty(); } }; @@ -665,6 +666,11 @@ public: m_oStyles.m_oPadding = oPadding; } + void SetMargin(const NSCSS::NSProperties::CIndent& oMargin) + { + m_oStyles.m_oMargin = oMargin; + } + const NSCSS::NSProperties::CIndent& GetPadding() const { return m_oStyles.m_oPadding; @@ -791,19 +797,19 @@ public: if (NSCSS::UnitMeasure::Percent == m_oStyles.m_oWidth.GetUnitMeasure()) oTable += L""; else - { - int nWidth; - if (NSCSS::UnitMeasure::None != m_oStyles.m_oWidth.GetUnitMeasure()) - nWidth = m_oStyles.m_oWidth.ToInt(NSCSS::UnitMeasure::Twips); - else - nWidth = static_cast(NSCSS::CUnitMeasureConverter::ConvertPx(m_oStyles.m_oWidth.ToDouble(), NSCSS::UnitMeasure::Twips, 96) + 0.5); - - oTable += L""; - } + oTable += L""; } else oTable += L""; + if (!m_oStyles.m_oMargin.GetLeft().Empty() && !m_oStyles.m_oMargin.GetLeft().Zero()) + { + if (NSCSS::UnitMeasure::Percent == m_oStyles.m_oMargin.GetLeft().GetUnitMeasure()) + oTable += L""; + else + oTable += L""; + } + if (!m_oStyles.m_wsAlign.empty()) oTable += L""; @@ -1176,7 +1182,7 @@ public: m_oStylesXml += L""; m_oStylesXml += L""; - m_oStylesXml += L""; +// m_oStylesXml += L""; } // normal по умолчанию @@ -1740,15 +1746,16 @@ private: readStream(&m_oDocXml, sSelectors, { false, false, true, false, -1, L"", L"" }); } - void readInside (NSStringUtils::CStringBuilder* oXml, std::vector& sSelectors, const CTextSettings& oTS, const std::wstring& sName) + bool readInside (NSStringUtils::CStringBuilder* oXml, std::vector& sSelectors, const CTextSettings& oTS, const std::wstring& sName) { + //TODO:: обработать все варианты return'а + if(sName == L"#text") { std::wstring sText = m_oLightReader.GetText(); - size_t find = sText.find_first_not_of(L" \n\t\r"); - if (find == std::wstring::npos) - return; + if (sText.end() == std::find_if_not(sText.begin(), sText.end(), [](wchar_t wchChar){ return iswspace(wchChar);})) + return false; bool bInT = m_bInT; @@ -1812,7 +1819,7 @@ private: } if (sText.empty()) - return; + return true; } else ReplaceSpaces(sText); @@ -1834,11 +1841,11 @@ private: CloseR(oXml); } - return; + return true; } std::wstring sNote = GetSubClass(oXml, sSelectors); - + bool bResult = true; // Ссылка // Область ссылки if(sName == L"a" || sName == L"area") @@ -1849,7 +1856,7 @@ private: { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Направление текста else if(sName == L"bdo") @@ -1862,21 +1869,21 @@ private: CTextSettings oTSBdo(oTS); oTSBdo.bBdo = (sDir == L"rtl"); - readStream(oXml, sSelectors, oTSBdo); + bResult = readStream(oXml, sSelectors, oTSBdo); } // Отмена направления текста else if(sName == L"bdi") { CTextSettings oTSBdo(oTS); oTSBdo.bBdo = false; - readStream(oXml, sSelectors, oTSBdo); + bResult = readStream(oXml, sSelectors, oTSBdo); } // Увеличивает размер шрифта else if(sName == L"big") { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Перенос строки else if(sName == L"br") @@ -1898,7 +1905,7 @@ private: { CTextSettings oTSP(oTS); oTSP.AddPStyle(L""); - readStream(oXml, sSelectors, oTSP); + bResult = readStream(oXml, sSelectors, oTSP); } // Цитата, обычно выделяется курсивом // Новый термин, обычно выделяется курсивом @@ -1909,7 +1916,7 @@ private: { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Код // Моноширинный шрифт, например, Consolas @@ -1918,14 +1925,14 @@ private: { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Зачеркнутый текст else if(sName == L"del" || sName == L"s") { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } else if(sName == L"font") { @@ -1966,7 +1973,7 @@ private: } } m_oLightReader.MoveToElement(); - readStream(oXml, sSelectors, oTS); + bResult = readStream(oXml, sSelectors, oTS); } // Картинки else if(sName == L"img") @@ -1976,14 +1983,14 @@ private: { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Выделенный текст, обычно выделяется желтым else if(sName == L"mark") { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Цитата, выделенная кавычками, обычно выделяется курсивом else if(sName == L"q") @@ -2014,21 +2021,21 @@ private: { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Уменьшает размер шрифта else if(sName == L"small") { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Текст нижнего регистра else if(sName == L"sub") { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Векторная картинка else if(sName == L"svg" || (sName.length() > 3 && sName.compare(sName.length() - 3, 3, L"svg") == 0)) @@ -2047,28 +2054,28 @@ private: { WriteEmptyParagraph(oXml, false, m_bInP); sSelectors.pop_back(); - return; + return true; } else if (sName == L"span") { if (sSelectors.back().m_wsClass == L"MsoFootnoteReference") { sSelectors.pop_back(); - return; + return false; } - readStream(oXml, sSelectors, oTS); + bResult = readStream(oXml, sSelectors, oTS); } else if (sName == L"nobr") { CTextSettings oTSPre(oTS); oTSPre.bPre = true; - readStream(oXml, sSelectors, oTSPre); + bResult = readStream(oXml, sSelectors, oTSPre); } // Без нового абзаца else if(sName == L"basefont" || sName == L"button" || sName == L"label" || sName == L"data" || sName == L"object" || sName == L"noscript" || sName == L"output" || sName == L"abbr" || sName == L"time" || sName == L"ruby" || sName == L"progress" || sName == L"hgroup" || sName == L"meter" || sName == L"acronym") - readStream(oXml, sSelectors, oTS); + bResult = readStream(oXml, sSelectors, oTS); // С нового абзаца else { @@ -2079,14 +2086,14 @@ private: { CTextSettings oTSR(oTS); oTSR.AddRStyle(L""); - readStream(oXml, sSelectors, oTSR); + bResult = readStream(oXml, sSelectors, oTSR); } // Определение термина, отступ от левого края else if(sName == L"dd") { CTextSettings oTSP(oTS); oTSP.sPStyle += L""; - readStream(oXml, sSelectors, oTSP); + bResult = readStream(oXml, sSelectors, oTSP); } // aside возможно использовать для сносок в epub else if (sName == L"aside" || sName == L"div") @@ -2123,7 +2130,7 @@ private: m_oNoteXml.WriteString(L""); } else - readStream(oXml, sSelectors, oTS); + bResult = readStream(oXml, sSelectors, oTS); } // С нового абзаца else if(sName == L"article" || sName == L"header" || sName == L"blockquote" || sName == L"main" || sName == L"dir" || @@ -2131,7 +2138,7 @@ private: sName == L"details" || sName == L"option" || sName == L"dt" || sName == L"p" || sName == L"section" || sName == L"figure" || sName == L"dl" || sName == L"legend" || sName == L"map" || sName == L"h1" || sName == L"h2" || sName == L"h3" || sName == L"h4" || sName == L"h5" || sName == L"h6") - readStream(oXml, sSelectors, oTS); + bResult = readStream(oXml, sSelectors, oTS); // Горизонтальная линия else if(sName == L"hr") { @@ -2168,7 +2175,7 @@ private: CTextSettings oTSPre(oTS); sSelectors.back().m_wsStyle += L"; font-family:Consolas"; oTSPre.bPre = true; - readStream(oXml, sSelectors, oTSPre); + bResult = readStream(oXml, sSelectors, oTSPre); } // Таблицы else if(sName == L"table") @@ -2178,16 +2185,16 @@ private: { CTextSettings oTSP(oTS); oTSP.AddPStyle(L""); - readStream(oXml, sSelectors, oTSP); + bResult = readStream(oXml, sSelectors, oTSP); } else if (sName == L"xml") { sSelectors.pop_back(); - return; + return false; } // Неизвестный тэг. Выделять ли его абзацем? else - readStream(oXml, sSelectors, oTS); + bResult =readStream(oXml, sSelectors, oTS); readNote(oXml, sSelectors, sNote); sNote = L""; @@ -2196,6 +2203,7 @@ private: } readNote(oXml, sSelectors, sNote); sSelectors.pop_back(); + return bResult; } bool readStream (NSStringUtils::CStringBuilder* oXml, std::vector& sSelectors, const CTextSettings& oTS, bool bInsertEmptyP = false) @@ -2212,11 +2220,24 @@ private: } return false; } + + bool bResult = false; + do { - readInside(oXml, sSelectors, oTS, m_oLightReader.GetName()); + if (readInside(oXml, sSelectors, oTS, m_oLightReader.GetName())) + bResult = true; } while(m_oLightReader.ReadNextSiblingNode2(nDeath)); - return true; + + if (!bResult && bInsertEmptyP) + { + wrP(oXml, sSelectors, oTS); + wrRPr(oXml, sSelectors, oTS); + CloseP(oXml, sSelectors); + m_bInP = false; + } + + return bResult; } void CalculateCellStyles(CTableCell* pCell, const std::vector& arSelectors) @@ -2410,6 +2431,7 @@ private: oTable.SetWidth(oStyle.m_oDisplay.GetWidth()); oTable.SetBorder(oStyle.m_oBorder); oTable.SetPadding(oStyle.m_oPadding); + oTable.SetMargin(oStyle.m_oMargin); oTable.SetAlign(oStyle.m_oDisplay.GetHAlign().ToWString()); //------