From 964c75126e6176a0faa36ea959581a3ef77c9d1e Mon Sep 17 00:00:00 2001 From: Kirill Poljakov Date: Thu, 16 Jun 2022 21:22:55 +0300 Subject: [PATCH] Improved working with styles --- .../3dParty/html/css/src/CCompiledStyle.cpp | 109 ++++++++++++--- .../html/css/src/CCssCalculator_Private.cpp | 3 +- Common/3dParty/html/css/src/ConstValues.h | 132 ++++++++++++++---- .../html/css/src/xhtml/CDocumentStyle.cpp | 25 ++-- HtmlFile2/htmlfile2.cpp | 40 +++++- 5 files changed, 249 insertions(+), 60 deletions(-) diff --git a/Common/3dParty/html/css/src/CCompiledStyle.cpp b/Common/3dParty/html/css/src/CCompiledStyle.cpp index 53c49ee0a1..c02c2edbb4 100644 --- a/Common/3dParty/html/css/src/CCompiledStyle.cpp +++ b/Common/3dParty/html/css/src/CCompiledStyle.cpp @@ -230,22 +230,30 @@ namespace NSCSS } CASE(L"line-height"): { - size_t unCoefficient = 1; + double dCoefficient = 1; const size_t unPositionImp = pPropertie.second.find(L"!i"); const size_t unPositionSymbol = pPropertie.second.find_first_of(L"abcdefghijklmnopqrstuvwxyz%"); if (unPositionSymbol == std::wstring::npos) - unCoefficient = m_pFont.GetSize(); + dCoefficient = m_pFont.GetSize(); if (unPositionImp == std::wstring::npos) { - const float fValue = wcstof(ConvertUnitMeasure(pPropertie.second, m_pFont.GetSize() * 1.2).c_str(), NULL); - m_pFont.SetLineHeight(std::to_wstring(fValue * unCoefficient), unLevel, bHardMode); + float fValue = wcstof(ConvertUnitMeasure(pPropertie.second, m_pFont.GetSize()).c_str(), NULL); + + if (m_pFont.GetSize() == fValue || bIsThereBorder) + fValue *= 1.2; + + m_pFont.SetLineHeight(std::to_wstring(fValue * dCoefficient), unLevel, bHardMode); } else if (unPositionImp != 0) { - const float fValue = wcstof(ConvertUnitMeasure(pPropertie.second.substr(0, unPositionImp - 1), m_pFont.GetSize() * 1.2).c_str(), NULL); - m_pFont.SetLineHeight(std::to_wstring(fValue * unCoefficient), unLevel, true); + float fValue = wcstof(ConvertUnitMeasure(pPropertie.second.substr(0, unPositionImp - 1), m_pFont.GetSize()).c_str(), NULL); + + if (m_pFont.GetSize() == fValue || bIsThereBorder) + fValue *= 1.2; + + m_pFont.SetLineHeight(std::to_wstring(fValue * dCoefficient), unLevel, true); m_pFont.SetImportantenLineHeight(true); } break; @@ -368,32 +376,52 @@ namespace NSCSS CASE(L"padding"): CASE(L"mso-padding-alt"): { - if (bIsThereBorder) - break; +// if (bIsThereBorder) +// break; + + bool bMarginPermission = m_pMargin.GetPermission(); + + m_pMargin.SetPermission(true); const size_t unPositionImp = pPropertie.second.find(L"!i"); if (unPositionImp == std::wstring::npos) { const std::wstring sValue = ConvertUnitMeasure(pPropertie.second, 540.0f, ScalingDirectionX); if (sValue.find_first_not_of(L" 0") != std::wstring::npos) + { + if (bIsThereBorder) + m_pMargin.AddMargin(L"0", 0, true); + m_pMargin.AddMargin(sValue, unLevel, bHardMode); + } } else if (unPositionImp != 0) { const std::wstring sValue = ConvertUnitMeasure(pPropertie.second.substr(0, unPositionImp - 1), 540.0f, ScalingDirectionX); if (sValue.find_first_not_of(L" 0") != std::wstring::npos) + { + if (bIsThereBorder) + m_pMargin.AddMargin(L"0", 0, true); + m_pMargin.AddMargin(sValue, unLevel, true); + } m_pMargin.SetImportantAll(true); } + m_pMargin.SetPermission(bMarginPermission); + break; } CASE(L"padding-top"): CASE(L"mso-padding-top-alt"): { - if (bIsThereBorder) - break; +// if (bIsThereBorder) +// break; + + bool bMarginPermission = m_pMargin.GetPermission(); + + m_pMargin.SetPermission(true); const size_t unPositionImp = pPropertie.second.find(L"!i"); if (unPositionImp == std::wstring::npos) @@ -411,14 +439,18 @@ namespace NSCSS m_pMargin.SetImportantTopSide(true); } + m_pMargin.SetPermission(bMarginPermission); + break; } CASE(L"padding-right"): CASE(L"mso-padding-right-alt"): { - if (bIsThereBorder) - break; +// if (bIsThereBorder) +// break; + bool bMarginPermission = m_pMargin.GetPermission(); + m_pMargin.SetPermission(true); const size_t unPositionImp = pPropertie.second.find(L"!i"); if (unPositionImp == std::wstring::npos) @@ -436,13 +468,19 @@ namespace NSCSS m_pMargin.SetImportantRightSide(true); } + m_pMargin.SetPermission(bMarginPermission); + break; } CASE(L"padding-bottom"): CASE(L"mso-padding-bottom-alt"): { - if (bIsThereBorder) - break; +// if (bIsThereBorder) +// break; + + bool bMarginPermission = m_pMargin.GetPermission(); + + m_pMargin.SetPermission(true); const size_t unPositionImp = pPropertie.second.find(L"!i"); if (unPositionImp == std::wstring::npos) @@ -460,13 +498,20 @@ namespace NSCSS m_pMargin.SetImportantBottomSide(true); } + m_pMargin.SetPermission(bMarginPermission); + break; } CASE(L"padding-left"): CASE(L"mso-padding-left-alt"): { - if (bIsThereBorder) - break; +// if (bIsThereBorder) +// break; + + bool bMarginPermission = m_pMargin.GetPermission(); + + m_pMargin.SetPermission(true); + const size_t unPositionImp = pPropertie.second.find(L"!i"); if (unPositionImp == std::wstring::npos) @@ -484,6 +529,8 @@ namespace NSCSS m_pMargin.SetImportantLeftSide(true); } + m_pMargin.SetPermission(bMarginPermission); + break; } // TEXT @@ -963,6 +1010,22 @@ namespace NSCSS m_pDisplay.SetWidth(ConvertUnitMeasure(pPropertie.second.substr(0, unPositionImp - 1), m_oDeviceWindow.m_ushWidth, ScalingDirectionX), unLevel, true); m_pDisplay.SetImportantWidth(true); } + + break; + } + CASE(L"height"): + { + const size_t unPositionImp = pPropertie.second.find(L"!i"); + if (unPositionImp == std::wstring::npos) + { + m_pDisplay.SetHeight(ConvertUnitMeasure(pPropertie.second, m_oDeviceWindow.m_ushWidth, ScalingDirectionY), unLevel, bHardMode); + } + else if (unPositionImp != 0) + { + m_pDisplay.SetHeight(ConvertUnitMeasure(pPropertie.second.substr(0, unPositionImp - 1), m_oDeviceWindow.m_ushWidth, ScalingDirectionY), unLevel, true); + m_pDisplay.SetImportantHeight(true); + } + break; } CASE(L"align"): @@ -989,11 +1052,12 @@ namespace NSCSS if (sStyle.empty()) return; - const std::vector arWords = NS_STATIC_FUNCTIONS::GetWordsWithSigns(sStyle, L" :;"); + const std::vector arWords = NS_STATIC_FUNCTIONS::GetWordsWithSigns(sStyle, L":;"); std::wstring sProperty, sValue; for (std::vector::const_iterator iWord = arWords.begin(); iWord != arWords.end(); ++iWord) + { if ((*iWord).back() == L':') { sProperty = *iWord; @@ -1002,9 +1066,15 @@ namespace NSCSS else { sValue += *iWord; - if ((*iWord).back() == L';') + + if (L' ' == sValue.front()) + sValue.erase(0, 1); + + if (!sValue.empty() && ((*iWord).back() == L';' || iWord == (arWords.end() - 1))) { - sValue.pop_back(); + if (sValue.back() == L';') + sValue.pop_back(); + std::transform(sProperty.begin(), sProperty.end(), sProperty.begin(), tolower); std::transform(sValue.begin(), sValue.end(), sValue.begin(), tolower); AddPropSel(sProperty, sValue, unLevel, bHardMode); @@ -1012,6 +1082,7 @@ namespace NSCSS sValue.clear(); } } + } if (!sProperty.empty() && !sValue.empty()) AddPropSel(sProperty, sValue, bHardMode); diff --git a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp index 4561ff329c..4a5a37a944 100644 --- a/Common/3dParty/html/css/src/CCssCalculator_Private.cpp +++ b/Common/3dParty/html/css/src/CCssCalculator_Private.cpp @@ -516,7 +516,8 @@ namespace NSCSS pStyle->AddStyle(arSelectors[i].m_sStyle, i + 1, true); else if (!bIsSettings) pStyle->AddStyle(arSelectors[i].m_sStyle, i + 1, true); - } + }else if (bIsSettings) + pStyle->AddStyle(arSelectors[i].m_sStyle, i + 1, true); } if (!bIsSettings) diff --git a/Common/3dParty/html/css/src/ConstValues.h b/Common/3dParty/html/css/src/ConstValues.h index b7b0a6c5fd..22e2109ddf 100644 --- a/Common/3dParty/html/css/src/ConstValues.h +++ b/Common/3dParty/html/css/src/ConstValues.h @@ -306,7 +306,7 @@ namespace NSCSS public: - Font() : fSize (fNoneValue), + Font() : fSize (24.0f), enStretch (FontStretch::none), enStyle (FontStyle::none), enVariant (FontVariant::none), @@ -886,7 +886,7 @@ namespace NSCSS void SetLineHeight(const std::wstring &sLineHeight, const unsigned int& unLevel, const bool& bHardMode = false) { - if (sLineHeight.empty() || (bImportants[5] && !bHardMode)) + if (sLineHeight.empty() || (bImportants[5] && !bHardMode) || unLevel <= arLevels[5]) return; if (sLineHeight == L"normal") @@ -1114,9 +1114,6 @@ namespace NSCSS bool Empty() const { - if (!bPermission) - return true; - return fTopSide == fNoneValue && fRightSide == fNoneValue && fBottomSide == fNoneValue && fLeftSide == fNoneValue; }; @@ -1325,33 +1322,70 @@ namespace NSCSS fLeftSide += wcstof(sLeftMargin.c_str(), NULL); } - std::wstring GetTopSide() const + bool GetPermission() const { - if (fTopSide < 0 || !bPermission) + return bPermission; + } + + double GetTopSide() const + { + if (fTopSide < 0) + return 0; + + return fTopSide; + } + + std::wstring GetTopSideW() const + { + if (fTopSide < 0) return std::wstring(); return std::to_wstring(static_cast(fTopSide * 10.0f + 0.5f)); } - std::wstring GetRightSide() const + double GetRightSide() const { - if (fRightSide < 0 || !bPermission) + if (fRightSide < 0) + return 0; + + return fRightSide; + } + + std::wstring GetRightSideW() const + { + if (fRightSide < 0) return std::wstring(); return (fRightSide >= -128.0f) ? std::to_wstring(static_cast(fRightSide * 10.0f + ((fLeftSide > 0) ? 0.5f : -0.5f))) : L"-1280"; } - std::wstring GetBottomSide() const + double GetBottomSide() const { - if (fBottomSide < 0 || !bPermission) + if (fBottomSide < 0) + return 0; + + return fBottomSide; + } + + std::wstring GetBottomSideW() const + { + if (fBottomSide < 0) return std::wstring(); return std::to_wstring(static_cast(fBottomSide * 10.0f + 0.5f)); } - std::wstring GetLeftSide() const + double GetLeftSide() const { - if (fLeftSide < 0 || !bPermission) + if (fLeftSide < 0) + return 0; + + return fLeftSide; + } + + std::wstring GetLeftSideW() const + { + if (fLeftSide < 0) return std::wstring(); return (fLeftSide >= -128.0f) ? std::to_wstring(static_cast(fLeftSide * 10.0f + ((fLeftSide > 0) ? 0.5f : -0.5f))) : L"-1280"; @@ -1481,7 +1515,7 @@ namespace NSCSS void SetAlign(const std::wstring& sAlign, const unsigned int& unLevel, const bool& bHardMode = false) { - if (sAlign.empty() || (bImportants[1] && !bHardMode)) + if (sAlign.empty() || (bImportants[1] && !bHardMode) || unLevel <= arLevels[1]) return; if (sAlign == L"center") @@ -1766,7 +1800,7 @@ namespace NSCSS bool Empty() const { - return fWidth < 0 && !bBlock; + return fWidth < 0; } void SetWidthWithoutChecking(const float& fWidth, const unsigned int& unLevel, const bool &bHardMode = false) @@ -2662,17 +2696,18 @@ namespace NSCSS { std::wstring wsDisplay; int nWidth; + int nHeight; std::wstring wsAlign; std::vector bImportants; std::vector arLevels; public: - Display() : wsDisplay(L"inline"), nWidth(-1), wsAlign(), bImportants{false, false, false}, arLevels{0, 0, 0} {}; + Display() : wsDisplay(L"inline"), nWidth(-1), nHeight(-1), wsAlign(), bImportants{false, false, false, false}, arLevels{0, 0, 0, 0} {}; void ClearImportants() { - bImportants = {false, false, false}; + bImportants = {false, false, false, false}; } Display operator+=(const Display& oDisplay) @@ -2682,6 +2717,7 @@ namespace NSCSS wsDisplay = oDisplay.wsDisplay; nWidth = oDisplay.nWidth; + nHeight = oDisplay.nHeight; wsAlign = oDisplay.wsAlign; return *this; @@ -2713,13 +2749,25 @@ namespace NSCSS oSecondDisplay.nWidth = -1; } - if (oFirstDisplay.bImportants[2] && !oSecondDisplay.bImportants[2] && !oFirstDisplay.wsAlign.empty()) + if (oFirstDisplay.bImportants[2] && !oSecondDisplay.bImportants[2] && oFirstDisplay.nHeight > 0) + oSecondDisplay.nHeight = -1; + else if (oSecondDisplay.bImportants[2] && !oFirstDisplay.bImportants[2] && oSecondDisplay.nHeight > 0) + oFirstDisplay.nHeight = -1; + else if (oSecondDisplay.nHeight > 0) + { + if (oFirstDisplay.arLevels[2] < oSecondDisplay.arLevels[2]) + oFirstDisplay.nHeight = -1; + else + oSecondDisplay.nHeight = -1; + } + + if (oFirstDisplay.bImportants[3] && !oSecondDisplay.bImportants[3] && !oFirstDisplay.wsAlign.empty()) oSecondDisplay.wsAlign.clear(); - else if (oSecondDisplay.bImportants[2] && !oFirstDisplay.bImportants[2] && !oSecondDisplay.wsAlign.empty()) + else if (oSecondDisplay.bImportants[3] && !oFirstDisplay.bImportants[3] && !oSecondDisplay.wsAlign.empty()) oFirstDisplay.wsAlign.clear(); else if (!oSecondDisplay.wsAlign.empty()) { - if (oFirstDisplay.arLevels[2] < oSecondDisplay.arLevels[2]) + if (oFirstDisplay.arLevels[3] < oSecondDisplay.arLevels[3]) oFirstDisplay.wsAlign.clear(); else oSecondDisplay.wsAlign.clear(); @@ -2728,17 +2776,17 @@ namespace NSCSS bool operator==(const Display& oDisplay) const { - return wsDisplay == oDisplay.wsDisplay && nWidth == oDisplay.nWidth && wsAlign == oDisplay.wsAlign; + return wsDisplay == oDisplay.wsDisplay && nWidth == oDisplay.nWidth && nHeight == oDisplay.nHeight && wsAlign == oDisplay.wsAlign; } bool Empty() const { - return (L"inline" == wsDisplay || wsDisplay.empty()) && (nWidth < 0) && (wsAlign.empty()); + return (L"inline" == wsDisplay || wsDisplay.empty()) && (nWidth < 0) && (nHeight < 0) && (wsAlign.empty()); } void SetImportantAll(const bool &bImportant) { - bImportants = {bImportant, bImportant, bImportant}; + bImportants = {bImportant, bImportant, bImportant, bImportant}; } void SetImportantDisplay(const bool &bImportant) @@ -2751,11 +2799,16 @@ namespace NSCSS bImportants[1] = bImportant; } - void SetImportantAlign(const bool& bImportant) + void SetImportantHeight(const bool &bImportant) { bImportants[2] = bImportant; } + void SetImportantAlign(const bool& bImportant) + { + bImportants[3] = bImportant; + } + void SetDisplay(const std::wstring& wsNewDisplay, const unsigned int& unLevel, const bool &bHardMode = false) { if (wsNewDisplay.empty() || (bImportants[0] && !bHardMode)) @@ -2785,15 +2838,34 @@ namespace NSCSS arLevels[1] = unLevel; nWidth = nValue; } + + void SetHeight(const std::wstring& wsNewValue, const unsigned int& unLevel, const bool &bHardMode = false) + { + if (wsNewValue.empty() || !iswdigit(wsNewValue[0]) || (bImportants[2] && !bHardMode)) + return; + + arLevels[2] = unLevel; + nHeight = std::stoi(wsNewValue); + } + + void SetHeight(int nValue, const unsigned int& unLevel, const bool &bHardMode = false) + { + if (bImportants[2] && !bHardMode) + return; + + arLevels[2] = unLevel; + nHeight = nValue; + } + void SetAlign(const std::wstring& sAlign, const unsigned int& unLevel, const bool& bHardMode = false) { - if (sAlign.empty() || (bImportants[2] && !bHardMode)) + if (sAlign.empty() || (bImportants[3] && !bHardMode)) return; if (L"center" == sAlign || L"left" == sAlign || L"start" == sAlign || L"right" == sAlign || L"end" == sAlign) { - arLevels[2] = unLevel; + arLevels[3] = unLevel; wsAlign = sAlign; } } @@ -2811,6 +2883,14 @@ namespace NSCSS return std::to_wstring(nWidth); } + std::wstring GetHeightW() const + { + if (nHeight < 0) + return std::wstring(); + + return std::to_wstring(nHeight); + } + std::wstring GetAlign() const { return wsAlign; diff --git a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp index d0593ea72b..91bef19ecb 100644 --- a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp +++ b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp @@ -254,10 +254,10 @@ namespace NSCSS std::wstring sInfValue; sInfValue.reserve(64); - if (!oStyle.m_pMargin.Empty()) + if (!oStyle.m_pMargin.Empty() && oStyle.m_pMargin.GetPermission()) { - const std::wstring& sLeftSide = oStyle.m_pMargin.GetLeftSide(); - const std::wstring& sRightSide = oStyle.m_pMargin.GetRightSide(); + const std::wstring& sLeftSide = oStyle.m_pMargin.GetLeftSideW(); + const std::wstring& sRightSide = oStyle.m_pMargin.GetRightSideW(); if (!sLeftSide.empty()) sInfValue += L"w:left=\"" + sLeftSide + L"\" "; @@ -274,22 +274,23 @@ namespace NSCSS std::wstring sSpacingValue; sSpacingValue.reserve(128); - if (!oStyle.m_pMargin.Empty()) + if (!oStyle.m_pMargin.Empty() && oStyle.m_pMargin.GetPermission()) { - sSpacingValue += L"w:after=\"" + oStyle.m_pMargin.GetTopSide() + L"\" "; - sSpacingValue += L"w:before=\"" + oStyle.m_pMargin.GetTopSide() + L"\" "; + sSpacingValue += L"w:after=\"" + oStyle.m_pMargin.GetTopSideW() + L"\" "; + sSpacingValue += L"w:before=\"" + oStyle.m_pMargin.GetTopSideW() + L"\" "; } - else if (!oStyle.m_pBorder.Empty()) - sSpacingValue += L"w:after=\"0\" w:before=\"0\" "; + else/* if (!oStyle.m_pBorder.Empty() || !oStyle.m_pMargin.GetPermission())*/ + sSpacingValue += L"w:after=\"0\" w:before=\"0\""; const std::wstring &sLineHeight = oStyle.m_pFont.GetLineHeight(); if (!sLineHeight.empty()) { - sSpacingValue += L"w:line=\"" + sLineHeight + L"\" "; - sSpacingValue += L"w:lineRule=\"auto\""; + sSpacingValue += L" w:line=\"" + sLineHeight + L"\" w:lineRule=\"auto\""; + } + else if (!oStyle.m_pBorder.Empty()) + { + sSpacingValue += L" w:line=\"" + std::to_wstring(static_cast(oStyle.m_pFont.GetSize() * 12 + 0.5f)) + L"\" w:lineRule=\"auto\""; } -// else if (!oStyle.m_pBorder.Empty()) -// sSpacingValue += L"w:line=\"240\" w:lineRule=\"auto\" "; if (!sSpacingValue.empty()) { diff --git a/HtmlFile2/htmlfile2.cpp b/HtmlFile2/htmlfile2.cpp index ed76b58db5..535d16a5cd 100644 --- a/HtmlFile2/htmlfile2.cpp +++ b/HtmlFile2/htmlfile2.cpp @@ -1065,6 +1065,8 @@ private: oXml->WriteString(L"\"/>"); j += nColspan - 1; } + + oXml->WriteString(L""); oXml->WriteString(L""); size_t nEmpty = oXml->GetCurSize(); m_bWasPStyle = false; @@ -1072,7 +1074,7 @@ private: GetSubClass(oXml, sSelectors); // Читаем th. Ячейка заголовка таблицы. Выравнивание посередине. Выделяется полужирным if(m_oLightReader.GetName() == L"th") - { + { CTextSettings oTSR(oTS); oTSR.sRStyle += L""; readStream(oXml, sSelectors, oTSR); @@ -1136,6 +1138,38 @@ private: std::wstring wsWidth = oStyle.m_pDisplay.GetWidthW(); std::wstring wsAlign = oStyle.m_pDisplay.GetAlign(); + if (wsAlign.empty()) + { + NSCSS::CNode oLastNode = sSelectors.back(); + sSelectors.pop_back(); + + NSCSS::CCompiledStyle oTempSettingsStyle = m_oStylesCalculator.GetCompiledStyle(sSelectors, true); + + wsAlign = oTempSettingsStyle.m_pText.GetAlign(); + + if (wsAlign.empty()) + { + NSCSS::CCompiledStyle oTempStyle = m_oStylesCalculator.GetCompiledStyle(sSelectors, false); + + wsAlign = oTempStyle.m_pText.GetAlign(); + } + + sSelectors.push_back(oLastNode); + } + + if (!oStyle.m_pMargin.Empty() && (0 < oStyle.m_pMargin.GetTopSide() || 0 < oStyle.m_pMargin.GetBottomSide())) + { + wsTable += L""; + + if (0 < oStyle.m_pMargin.GetTopSide()) + wsTable += L"(oStyle.m_pMargin.GetTopSide() * 20 + 0.5f)) + L"\" w:type=\"dxa\"/>"; + + if (0 < oStyle.m_pMargin.GetBottomSide()) + wsTable += L"(oStyle.m_pMargin.GetBottomSide() * 20 + 0.5f)) + L"\" w:type=\"dxa\"/>"; + + wsTable += L""; + } + if (!wsWidth.empty()) wsTable += L""; else if (m_oStylesCalculator.GetSizeDeviceWindow().m_ushWidth != 0) @@ -1615,7 +1649,9 @@ private: size_t i = 0; while(i != sSelectors.size()) { - if(rStyle.find(L' ' + sSelectors[i].m_sName + L' ') != std::wstring::npos) + if(rStyle.find(L' ' + sSelectors[i].m_sName + L' ') != std::wstring::npos && + sSelectors[i].m_sClass.empty() && sSelectors[i].m_sId.empty() && + sSelectors[i].m_sStyle.empty() && sSelectors[i].m_mAttrs.empty()) { temporary.push_back(std::make_pair(i, sSelectors[i])); sSelectors.erase(sSelectors.begin() + i);