From d7b435a446eb1ec14e91a77781eba7eb70ba446c Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Fri, 13 Dec 2024 12:28:13 +0300 Subject: [PATCH 01/17] Delete unused file --- DocxRenderer/src/logic/BaseItem.cpp | 126 ----------------- DocxRenderer/src/logic/Page.cpp | 20 ++- DocxRenderer/src/logic/elements/Shape.cpp | 161 +++++++--------------- DocxRenderer/src/logic/elements/Shape.h | 2 + 4 files changed, 64 insertions(+), 245 deletions(-) delete mode 100644 DocxRenderer/src/logic/BaseItem.cpp diff --git a/DocxRenderer/src/logic/BaseItem.cpp b/DocxRenderer/src/logic/BaseItem.cpp deleted file mode 100644 index 9bd43be79a..0000000000 --- a/DocxRenderer/src/logic/BaseItem.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include "BaseItem.h" -#include "../resources/Constants.h" -#include - -namespace NSDocxRenderer -{ - CBaseItem& CBaseItem::operator=(const CBaseItem& oSrc) - { - if (this == &oSrc) - { - return *this; - } - - m_eType = oSrc.m_eType; - m_bIsNotNecessaryToUse = oSrc.m_bIsNotNecessaryToUse; - - m_dLeft = oSrc.m_dLeft; - m_dTop = oSrc.m_dTop; - m_dWidth = oSrc.m_dWidth; - m_dHeight = oSrc.m_dHeight; - m_dBaselinePos = oSrc.m_dBaselinePos; - m_dRight = oSrc.m_dRight; - - return *this; - } - - bool CBaseItem::IsBigger(const CBaseItem* oSrc) - { - return (m_dLeft > oSrc->m_dLeft) ? true : false; - } - - bool CBaseItem::IsBiggerOrEqual(const CBaseItem* oSrc) - { - return (m_dLeft >= oSrc->m_dLeft) ? true : false; - } - - eVerticalCrossingType CBaseItem::GetVerticalCrossingType(const CBaseItem* oSrc) - { - if (m_dTop > oSrc->m_dTop && m_dBaselinePos < oSrc->m_dBaselinePos) - { - return eVerticalCrossingType::vctCurrentInsideNext; - } - else if (m_dTop < oSrc->m_dTop && m_dBaselinePos > oSrc->m_dBaselinePos) - { - return eVerticalCrossingType::vctCurrentOutsideNext; - } - else if (m_dTop < oSrc->m_dTop && m_dBaselinePos < oSrc->m_dBaselinePos && m_dBaselinePos > oSrc->m_dTop) - { - return eVerticalCrossingType::vctCurrentAboveNext; - } - else if (m_dTop > oSrc->m_dTop && m_dBaselinePos > oSrc->m_dBaselinePos && m_dTop < oSrc->m_dBaselinePos) - { - return eVerticalCrossingType::vctCurrentBelowNext; - } - else if (m_dTop == oSrc->m_dTop && m_dBaselinePos == oSrc->m_dBaselinePos && - m_dLeft == oSrc->m_dLeft && m_dRight == oSrc->m_dRight) - { - return eVerticalCrossingType::vctDublicate; - } - else if (fabs(m_dTop - oSrc->m_dTop) < c_dTHE_SAME_STRING_Y_PRECISION_MM) - { - return eVerticalCrossingType::vctTopBordersMatch; - } - else if (fabs(m_dBaselinePos - oSrc->m_dBaselinePos) < c_dTHE_SAME_STRING_Y_PRECISION_MM) - { - return eVerticalCrossingType::vctBottomBordersMatch; - } - else if (m_dBaselinePos < oSrc->m_dTop) - { - return eVerticalCrossingType::vctNoCrossingCurrentAboveNext; - } - else if (m_dTop > oSrc->m_dBaselinePos) - { - return eVerticalCrossingType::vctNoCrossingCurrentBelowNext; - } - else - { - return eVerticalCrossingType::vctUnknown; - } - } - - eHorizontalCrossingType CBaseItem::GetHorizontalCrossingType(const CBaseItem* oSrc) - { - if (m_dLeft > oSrc->m_dLeft && m_dRight < oSrc->m_dRight) - { - return eHorizontalCrossingType::hctCurrentInsideNext; - } - else if (m_dLeft < oSrc->m_dLeft && m_dRight > oSrc->m_dRight) - { - return eHorizontalCrossingType::hctCurrentOutsideNext; - } - else if (m_dLeft < oSrc->m_dLeft && m_dRight < oSrc->m_dRight && m_dRight > oSrc->m_dLeft) - { - return eHorizontalCrossingType::hctCurrentLeftOfNext; - } - else if (m_dLeft > oSrc->m_dLeft && m_dRight > oSrc->m_dRight && m_dLeft < oSrc->m_dRight) - { - return eHorizontalCrossingType::hctCurrentRightOfNext; - } - else if (m_dLeft == oSrc->m_dLeft && m_dRight == oSrc->m_dRight && - m_dTop == oSrc->m_dTop && m_dBaselinePos == oSrc->m_dBaselinePos) - { - return eHorizontalCrossingType::hctDublicate; - } - else if (fabs(m_dLeft - oSrc->m_dLeft) < c_dTHE_SAME_STRING_Y_PRECISION_MM) - { - return eHorizontalCrossingType::hctLeftBordersMatch; - } - else if (fabs(m_dRight - oSrc->m_dRight) < c_dTHE_SAME_STRING_Y_PRECISION_MM) - { - return eHorizontalCrossingType::hctRightBordersMatch; - } - else if (m_dRight < oSrc->m_dLeft) - { - return eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext; - } - else if (m_dLeft > oSrc->m_dRight) - { - return eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext; - } - else - { - return eHorizontalCrossingType::hctUnknown; - } - } -} diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 9efdefbc33..5881e5d117 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -389,18 +389,20 @@ namespace NSDocxRenderer { m_arConts = std::move(m_oContBuilder.GetConts()); - // analyze shapes (get type of lines etc) - AnalyzeShapes(); - // build m_arDiacriticalSymbols BuildDiacriticalSymbols(); // build text lines from m_arConts BuildTextLines(); + + // analyze shapes (get type of lines etc) + AnalyzeShapes(); + // analyze text lines and conts inside AnalyzeTextLines(); + // merge conts in text lines MergeConts(); @@ -424,13 +426,11 @@ namespace NSDocxRenderer } void CPage::ReorderShapesForPptx() { - using shape_ptr_t = std::shared_ptr; - // переместим nullptr в конец и удалим auto right = MoveNullptr(m_arShapes.begin(), m_arShapes.end()); m_arShapes.erase(right, m_arShapes.end()); - std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& s1, const shape_ptr_t& s2) { + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& s1, const CShape::shape_ptr_t& s2) { if (s1->m_bIsBehindDoc && !s2->m_bIsBehindDoc) return true; if (!s1->m_bIsBehindDoc && s2->m_bIsBehindDoc) return false; return s1->m_nOrder < s2->m_nOrder; @@ -505,8 +505,7 @@ namespace NSDocxRenderer if (m_arShapes.empty()) return; - using shape_ptr_t = std::shared_ptr; - std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& a, const shape_ptr_t& b) { + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& a, const CShape::shape_ptr_t& b) { if (!a) return false; if (!b) return true; return a->m_nOrder < b->m_nOrder; @@ -560,8 +559,7 @@ namespace NSDocxRenderer void CPage::DetermineLinesType() { - using shape_ptr_t = std::shared_ptr; - std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& a, const shape_ptr_t& b) { + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& a, const CShape::shape_ptr_t& b) { return a->m_dLeft < b->m_dLeft; }); @@ -607,7 +605,7 @@ namespace NSDocxRenderer auto& second_shape = m_arShapes[curr_shape_indexes[k]]; CShape::CheckLineType(first_shape, second_shape, k == curr_shape_indexes.size() - 1); - if(!m_arShapes[j]) + if (!m_arShapes[j]) { j = k; k++; diff --git a/DocxRenderer/src/logic/elements/Shape.cpp b/DocxRenderer/src/logic/elements/Shape.cpp index 4efd97251a..4b31f34fdf 100644 --- a/DocxRenderer/src/logic/elements/Shape.cpp +++ b/DocxRenderer/src/logic/elements/Shape.cpp @@ -234,69 +234,49 @@ namespace NSDocxRenderer void CShape::DetermineGraphicsType(double dWidth, double dHeight,size_t nPeacks, size_t nCurves) noexcept { - //note параллельно для каждой текстовой строки создается шейп, который содержит цвет фона для данного текста. - if ((m_bIsNoStroke && m_bIsNoFill) || - (m_oBrush.Color1 == c_iWhiteColor && m_oPen.Color == c_iWhiteColor)) - { + if ((m_bIsNoStroke && m_bIsNoFill) || (m_oBrush.Color1 == c_iWhiteColor && m_oPen.Color == c_iWhiteColor)) m_eGraphicsType = eGraphicsType::gtNoGraphics; - } else if ((nPeacks == 5 || nPeacks == 2) && !nCurves) //1 move + 4 Peacks или 2 Peacks { m_eGraphicsType = eGraphicsType::gtRectangle; - if (dHeight < 0.7) { - if (dWidth > 2.0) //note длинное тире - 2.8mm у times new roman - { + if (dWidth > 2.0) // длинное тире - 2.8mm у times new roman m_eSimpleLineType = eSimpleLineType::sltHLongDash; - } - else if (dWidth > 0.7) //минимальное тире - 0.75mm у dotDotDash - { + else if (dWidth > 0.7) // минимальное тире - 0.75mm у dotDotDash m_eSimpleLineType = eSimpleLineType::sltHDash; - } - else //максимальная точка - 0.5mm - { - m_eSimpleLineType = eSimpleLineType::sltHDot; - } + else + m_eSimpleLineType = eSimpleLineType::sltHDot; // максимальная точка - 0.5mm } else if (dWidth < 0.7) { - if (dHeight > 2.0) //note длинное тире - 2.8mm у times new roman - { + if (dHeight > 2.0) // длинное тире - 2.8mm у times new roman m_eSimpleLineType = eSimpleLineType::sltVLongDash; - } - else if (dHeight > 0.7) //минимальное тире - 0.75mm у dotDotDash - { + else if (dHeight > 0.7) // минимальное тире - 0.75mm у dotDotDash m_eSimpleLineType = eSimpleLineType::sltVDash; - } - else //максимальна точка - 0.5mm - { - m_eSimpleLineType = eSimpleLineType::sltVDot; - } + else + m_eSimpleLineType = eSimpleLineType::sltVDot; // максимальна точка - 0.5mm } } - else if (nCurves > 0 && nPeacks <= 1) //1 move + else if (nCurves > 0 && nPeacks <= 1) // 1 move { m_eGraphicsType = eGraphicsType::gtCurve; if (dHeight < dWidth) - { m_eSimpleLineType = eSimpleLineType::sltHWave; - } else - { m_eSimpleLineType = eSimpleLineType::sltVWave; - } } else if (nCurves > 0 && nPeacks > 1) - { m_eGraphicsType = eGraphicsType::gtComplicatedFigure; - } } bool CShape::IsItFitLine() const noexcept { - return (m_eGraphicsType == eGraphicsType::gtRectangle && (m_eSimpleLineType == eSimpleLineType::sltHDot || m_eSimpleLineType == eSimpleLineType::sltHDash || m_eSimpleLineType == eSimpleLineType::sltHLongDash)) || - (m_eGraphicsType == eGraphicsType::gtCurve && m_eSimpleLineType == eSimpleLineType::sltHWave); + return (m_eGraphicsType == eGraphicsType::gtRectangle && ( + m_eSimpleLineType == eSimpleLineType::sltHDot || + m_eSimpleLineType == eSimpleLineType::sltHDash || + m_eSimpleLineType == eSimpleLineType::sltHLongDash)) || + (m_eGraphicsType == eGraphicsType::gtCurve && m_eSimpleLineType == eSimpleLineType::sltHWave); } bool CShape::IsCorrelated(std::shared_ptr pShape) const noexcept @@ -323,7 +303,7 @@ namespace NSDocxRenderer void CShape::CheckLineType(std::shared_ptr& pFirstShape) { - if(!pFirstShape) + if (!pFirstShape) return; if (pFirstShape->m_eLineType == eLineType::ltUnknown && pFirstShape->m_eSimpleLineType == eSimpleLineType::sltHLongDash) @@ -338,103 +318,68 @@ namespace NSDocxRenderer return; if (!pFirstShape->IsItFitLine() || !pSecondShape->IsItFitLine() || !pFirstShape->IsCorrelated(pSecondShape) || - fabs(pFirstShape->m_dHeight - pSecondShape->m_dHeight) > c_dGRAPHICS_ERROR_IN_LINES_MM) // линия должна быть одного размера по высоте + fabs(pFirstShape->m_dHeight - pSecondShape->m_dHeight) > c_dGRAPHICS_ERROR_IN_LINES_MM) { + return; // линия должна быть одного размера по высоте + } + + auto set_line_type = [] (shape_ptr_t& master, shape_ptr_t& slave, eLineType type) { + master->m_eLineType = type; + master->RecalcWithNewItem(slave.get()); + master->m_oVector.Join(std::move(slave->m_oVector)); + slave = nullptr; + }; + + // проверка на двойную линию + if (pFirstShape->m_eLineType == eLineType::ltDouble) + { + if (pFirstShape->m_dTop < pSecondShape->m_dTop) + set_line_type(pFirstShape, pSecondShape, eLineType::ltDouble); + else + set_line_type(pSecondShape, pFirstShape, eLineType::ltDouble); + + return; + } + if (pFirstShape->m_eLineType == eLineType::ltWavyDouble) + { + if (pFirstShape->m_dTop < pSecondShape->m_dTop) + set_line_type(pFirstShape, pSecondShape, eLineType::ltWavyDouble); + else + set_line_type(pSecondShape, pFirstShape, eLineType::ltWavyDouble); + return; } - // проверка на двойную линию - if (pFirstShape->m_eLineType == eLineType::ltDouble || pFirstShape->m_eLineType == eLineType::ltWavyDouble) - { - if (pFirstShape->m_eLineType == eLineType::ltDouble) - { - if (pFirstShape->m_dTop < pSecondShape->m_dTop) - { - pFirstShape->m_eLineType = eLineType::ltDouble; - pFirstShape->RecalcWithNewItem(pSecondShape.get()); - pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); - pSecondShape = nullptr; - } - else - { - pSecondShape->m_eLineType = eLineType::ltDouble; - pSecondShape->RecalcWithNewItem(pFirstShape.get()); - pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); - pFirstShape = nullptr; - } - } - else if (pFirstShape->m_eLineType == eLineType::ltWavyDouble) - { - if (pFirstShape->m_dTop < pSecondShape->m_dTop) - { - pFirstShape->m_eLineType = eLineType::ltWavyDouble; - pFirstShape->RecalcWithNewItem(pSecondShape.get()); - pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); - pSecondShape = nullptr; - } - else - { - pSecondShape->m_eLineType = eLineType::ltWavyDouble; - pSecondShape->RecalcWithNewItem(pFirstShape.get()); - pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); - pFirstShape = nullptr; - } - } - return; - } else if (fabs(pFirstShape->m_dTop - pSecondShape->m_dTop) < c_dGRAPHICS_ERROR_IN_LINES_MM * 5 && fabs(pFirstShape->m_dWidth - pSecondShape->m_dWidth) < c_dGRAPHICS_ERROR_IN_LINES_MM && fabs(pFirstShape->m_dLeft - pSecondShape->m_dLeft) < c_dGRAPHICS_ERROR_IN_LINES_MM) { - //Условие первого определения + // условие первого определения if (pFirstShape->m_eSimpleLineType == eSimpleLineType::sltHLongDash && pSecondShape->m_eSimpleLineType == eSimpleLineType::sltHLongDash) { if (pFirstShape->m_dTop < pSecondShape->m_dTop) - { - pFirstShape->m_eLineType = eLineType::ltDouble; - pFirstShape->RecalcWithNewItem(pSecondShape.get()); - pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); - pSecondShape = nullptr; - } + set_line_type(pFirstShape, pSecondShape, eLineType::ltDouble); else - { - pSecondShape->m_eLineType = eLineType::ltDouble; - pSecondShape->RecalcWithNewItem(pFirstShape.get()); - pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); - pFirstShape = nullptr; - } + set_line_type(pSecondShape, pFirstShape, eLineType::ltDouble); } else if (pFirstShape->m_eSimpleLineType == eSimpleLineType::sltHWave && pSecondShape->m_eSimpleLineType == eSimpleLineType::sltHWave) { if (pFirstShape->m_dTop < pSecondShape->m_dTop) - { - pFirstShape->m_eLineType = eLineType::ltWavyDouble; - pFirstShape->RecalcWithNewItem(pSecondShape.get()); - pFirstShape->m_oVector.Join(std::move(pSecondShape->m_oVector)); - pSecondShape = nullptr; - } + set_line_type(pFirstShape, pSecondShape, eLineType::ltWavyDouble); else - { - pSecondShape->m_eLineType = eLineType::ltWavyDouble; - pSecondShape->RecalcWithNewItem(pFirstShape.get()); - pSecondShape->m_oVector.Join(std::move(pFirstShape->m_oVector)); - pFirstShape = nullptr; - } + set_line_type(pSecondShape, pFirstShape, eLineType::ltWavyDouble); } return; } else if (fabs(pFirstShape->m_dTop - pSecondShape->m_dTop) > c_dGRAPHICS_ERROR_IN_LINES_MM) - { - // все должно быть на одной линии - return; - } + return; // все должно быть на одной линии // теперь считаем, что графика находится на одной линии - if (fabs(pFirstShape->m_dLeft +pFirstShape->m_dWidth - pSecondShape->m_dLeft) > c_dGRAPHICS_ERROR_IN_LINES_MM * 5) + // расстояние между объектами на одной линии должно быть небольшим + if (fabs(pFirstShape->m_dLeft + pFirstShape->m_dWidth - pSecondShape->m_dLeft) > c_dGRAPHICS_ERROR_IN_LINES_MM * 5) { - // расстояние между объектами на одной линии должно быть небольшим if (pFirstShape->m_eLineType == eLineType::ltUnknown && pFirstShape->m_eSimpleLineType == eSimpleLineType::sltHLongDash) - pFirstShape->m_eLineType =pFirstShape-> m_dHeight > 0.3 ? eLineType::ltThick : eLineType::ltSingle; + pFirstShape->m_eLineType = pFirstShape-> m_dHeight > 0.3 ? eLineType::ltThick : eLineType::ltSingle; else if (pFirstShape->m_eLineType == eLineType::ltUnknown && pFirstShape->m_eSimpleLineType == eSimpleLineType::sltHWave) pFirstShape->m_eLineType = pFirstShape->m_oPen.Size > 0.3 ? eLineType::ltWavyHeavy : eLineType::ltWave; diff --git a/DocxRenderer/src/logic/elements/Shape.h b/DocxRenderer/src/logic/elements/Shape.h index 317ac2d0e4..09801bcdd7 100644 --- a/DocxRenderer/src/logic/elements/Shape.h +++ b/DocxRenderer/src/logic/elements/Shape.h @@ -31,6 +31,8 @@ namespace NSDocxRenderer }; public: + using shape_ptr_t = std::shared_ptr; + eShapeType m_eType {eShapeType::stUnknown}; NSStructures::CBrush m_oBrush{}; From f9952d0f94d89b046fa05ae1430dcdcea44724fe Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Fri, 13 Dec 2024 15:50:32 +0300 Subject: [PATCH 02/17] Refactoring for future tables --- DocxRenderer/src/logic/Page.cpp | 230 +++++++++---------- DocxRenderer/src/logic/Page.h | 95 +++++--- DocxRenderer/src/logic/elements/ContText.cpp | 5 + DocxRenderer/src/logic/elements/ContText.h | 3 +- 4 files changed, 182 insertions(+), 151 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 5881e5d117..bd72268654 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -387,36 +387,25 @@ namespace NSDocxRenderer void CPage::Analyze() { - m_arConts = std::move(m_oContBuilder.GetConts()); + // building objects from symbols + m_arConts = m_oContBuilder.GetConts(); + m_arDiacriticalSymbols = MoveDiacriticalSymbols(); + m_arTextLines = BuildTextLines(); - // build m_arDiacriticalSymbols - BuildDiacriticalSymbols(); - - // build text lines from m_arConts - BuildTextLines(); - - - // analyze shapes (get type of lines etc) + // analyzing data AnalyzeShapes(); - - // analyze text lines and conts inside AnalyzeTextLines(); + // building final objects + m_arParagraphs = BuildParagraphs(); + // TODO: tables - // merge conts in text lines - MergeConts(); - - // build paragraphs from m_arTextLines - BuildParagraphes(); - - // calc sizes on selected fonts for m_arConts + // post analyze CalcSelected(); - - // merge shapes MergeShapes(); - - // calc shapes paths with no rotation to write CalcShapesRotation(); + + m_arOutputObjects = BuildOutputObjects(); } void CPage::Record(NSStringUtils::CStringBuilder& oWriter, bool bIsLastPage) @@ -437,22 +426,20 @@ namespace NSDocxRenderer }); } - void CPage::BuildDiacriticalSymbols() + std::vector> CPage::MoveDiacriticalSymbols() { - for (size_t i = 0; i < m_arConts.size(); i++) - { - if (m_arConts[i] && m_arConts[i]->GetText().length() == 1) - { - const auto& text = m_arConts[i]->GetText(); - if (CContText::IsUnicodeDiacriticalMark(text.at(0))) - m_arDiacriticalSymbols.push_back(std::move(m_arConts[i])); - } - } + std::vector> diac_symbols; + for (auto& cont : m_arConts) + if (cont && cont->IsDiacritical()) + diac_symbols.push_back(std::move(cont)); + return diac_symbols; } - void CPage::BuildTextLines() + std::vector> CPage::BuildTextLines() { std::shared_ptr curr_line = nullptr; + std::vector> text_lines; + for (auto& cont : m_arConts) { if (!cont) @@ -465,11 +452,11 @@ namespace NSDocxRenderer } bool skip = false; - for (size_t i = 0; i < m_arTextLines.size(); ++i) + for (size_t i = 0; i < text_lines.size(); ++i) { - if (fabs(m_arTextLines[i]->m_dBaselinePos - cont->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) + if (fabs(text_lines[i]->m_dBaselinePos - cont->m_dBaselinePos) <= c_dTHE_SAME_STRING_Y_PRECISION_MM) { - curr_line = m_arTextLines[i]; + curr_line = text_lines[i]; cont->m_bPossibleSplit = true; curr_line->AddCont(cont); skip = true; @@ -481,13 +468,13 @@ namespace NSDocxRenderer curr_line = std::make_shared(); curr_line->AddCont(cont); - m_arTextLines.push_back(curr_line); + text_lines.push_back(curr_line); } - for (size_t i = 0; i < m_arTextLines.size(); i++) + for (size_t i = 0; i < text_lines.size(); i++) { bool only_spaces = true; - for (auto& cont : m_arTextLines[i]->m_arConts) + for (auto& cont : text_lines[i]->m_arConts) { if (!cont->IsOnlySpaces()) { @@ -496,8 +483,9 @@ namespace NSDocxRenderer } } if (only_spaces) - m_arTextLines.erase(m_arTextLines.begin() + i, m_arTextLines.begin() + i + 1); + text_lines.erase(text_lines.begin() + i, text_lines.begin() + i + 1); } + return text_lines; } void CPage::MergeShapes() @@ -532,6 +520,58 @@ namespace NSDocxRenderer } } + std::vector> CPage::BuildOutputObjects() + { + std::vector> output_objects; + + if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || + m_eTextAssociationType == TextAssociationType::tatPlainLine) + { + CBaseItem* prev_p = nullptr; + + size_t first_index = 0; + size_t second_index = first_index + 1; + + for (; first_index < m_arParagraphs.size(); first_index = second_index++) + { + auto& first_p = m_arParagraphs[first_index]; + if (second_index != m_arParagraphs.size()) + { + auto& second_p = m_arParagraphs[second_index]; + while (second_index < m_arParagraphs.size() && first_p->m_dBaselinePos > second_p->m_dTop) + second_index++; + } + + if (second_index - first_index == 1) + { + auto& p = m_arParagraphs[first_index]; + + if (!prev_p) + p->m_dSpaceBefore = p->m_dTop + c_dCORRECTION_FOR_FIRST_PARAGRAPH; + else + p->m_dSpaceBefore = p->m_dTop - prev_p->m_dBaselinePos; + + output_objects.push_back(p); + prev_p = p.get(); + } + else + { + for (size_t j = first_index; j < second_index; ++j) + m_arShapes.push_back(CreateSingleParagraphShape(m_arParagraphs[j])); + } + } + } + + else if (m_eTextAssociationType == TextAssociationType::tatParagraphToShape || + m_eTextAssociationType == TextAssociationType::tatShapeLine) + { + for (auto& p : m_arParagraphs) + m_arShapes.push_back(CreateSingleParagraphShape(p)); + } + + return output_objects; + } + void CPage::CalcSelected() { for (auto& line : m_arTextLines) @@ -554,10 +594,10 @@ namespace NSDocxRenderer void CPage::AnalyzeShapes() { - DetermineLinesType(); + AnalyzeLinesType(); } - void CPage::DetermineLinesType() + void CPage::AnalyzeLinesType() { std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& a, const CShape::shape_ptr_t& b) { return a->m_dLeft < b->m_dLeft; @@ -627,23 +667,24 @@ namespace NSDocxRenderer return a->m_dBaselinePos < b->m_dBaselinePos; }); - // analyze drop caps (creates shapes) AnalyzeDropCaps(); - - // analyze conts in text lines AnalyzeConts(); - - // Strikeout, underline, outline, highlight AnalyzeEffects(); - - // diacritical symbols AddDiacriticalSymbols(); - - // super/subscript MergeLinesByVertAlignType(); - - // delete lines out of page DeleteTextClipPage(); + MergeConts(); + SplitLines(); + AnalyzeOverlapLines(); + + // переместим nullptr в конец и удалим + auto right = MoveNullptr(m_arTextLines.begin(), m_arTextLines.end()); + m_arTextLines.erase(right, m_arTextLines.end()); + + using line_ptr_t = std::shared_ptr; + std::sort(m_arTextLines.begin(), m_arTextLines.end(), [] (const line_ptr_t& a, const line_ptr_t& b) { + return a->m_dBaselinePos < b->m_dBaselinePos; + }); } void CPage::AnalyzeDropCaps() @@ -1102,13 +1143,8 @@ namespace NSDocxRenderer oWriter.WriteString(L""); } - for (size_t i = 0; i < m_arOutputObjects.size(); ++i) - { - auto& pObj = m_arOutputObjects[i]; - CParagraph* pParagraph = nullptr; - if((pParagraph = dynamic_cast(pObj.get())) != nullptr) - pParagraph->ToXml(oWriter); - } + for (auto& obj : m_arOutputObjects) + obj->ToXml(oWriter); } void CPage::MergeConts() @@ -1249,6 +1285,10 @@ namespace NSDocxRenderer for (size_t index = 0; index < m_arTextLines.size(); ++index) { auto& line = m_arTextLines[index]; + + if (!line) + continue; + bool next_line = false; for (size_t i = 0; i < line->m_arConts.size(); ++i) { @@ -1299,10 +1339,6 @@ namespace NSDocxRenderer if (next_line) continue; } - using line_ptr_t = std::shared_ptr; - std::sort(m_arTextLines.begin(), m_arTextLines.end(), [] (const line_ptr_t& a, const line_ptr_t& b) { - return a->m_dBaselinePos < b->m_dBaselinePos; - }); } std::vector>> CPage::GetLinesByGroups() @@ -1377,13 +1413,13 @@ namespace NSDocxRenderer return line_groups; } - void CPage::BuildParagraphes() + void CPage::AnalyzeOverlapLines() { auto no_crossing = [] (const eHorizontalCrossingType& h_type, const eVerticalCrossingType& v_type) { return h_type == eHorizontalCrossingType::hctNoCrossingCurrentLeftOfNext || - h_type == eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext || - v_type == eVerticalCrossingType::vctNoCrossingCurrentAboveNext || - v_type == eVerticalCrossingType::vctNoCrossingCurrentBelowNext; + h_type == eHorizontalCrossingType::hctNoCrossingCurrentRightOfNext || + v_type == eVerticalCrossingType::vctNoCrossingCurrentAboveNext || + v_type == eVerticalCrossingType::vctNoCrossingCurrentBelowNext; }; // линии из которых сделаем шейпы @@ -1423,18 +1459,13 @@ namespace NSDocxRenderer } } } + } + std::vector> CPage::BuildParagraphs() + { if (m_arTextLines.empty()) - return; + return {}; - // переместим nullptr в конец и удалим - auto right = MoveNullptr(m_arTextLines.begin(), m_arTextLines.end()); - m_arTextLines.erase(right, m_arTextLines.end()); - - if (m_arTextLines.empty()) - return; - - SplitLines(); auto line_groups = GetLinesByGroups(); std::vector> ar_paragraphs; @@ -1789,50 +1820,7 @@ namespace NSDocxRenderer return a->m_dBaselinePos < b->m_dBaselinePos; }); - if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || - m_eTextAssociationType == TextAssociationType::tatPlainLine) - { - CBaseItem* prev_p = nullptr; - - size_t first_index = 0; - size_t second_index = first_index + 1; - - for (; first_index < ar_paragraphs.size(); first_index = second_index++) - { - auto& first_p = ar_paragraphs[first_index]; - if (second_index != ar_paragraphs.size()) - { - auto& second_p = ar_paragraphs[second_index]; - while (second_index < ar_paragraphs.size() && first_p->m_dBaselinePos > second_p->m_dTop) - second_index++; - } - - if (second_index - first_index == 1) - { - auto& p = ar_paragraphs[first_index]; - - if (!prev_p) - p->m_dSpaceBefore = p->m_dTop + c_dCORRECTION_FOR_FIRST_PARAGRAPH; - else - p->m_dSpaceBefore = p->m_dTop - prev_p->m_dBaselinePos; - - m_arOutputObjects.push_back(p); - prev_p = p.get(); - } - else - { - for (size_t j = first_index; j < second_index; ++j) - m_arShapes.push_back(CreateSingleParagraphShape(ar_paragraphs[j])); - } - } - } - - else if (m_eTextAssociationType == TextAssociationType::tatParagraphToShape || - m_eTextAssociationType == TextAssociationType::tatShapeLine) - { - for (auto& p : ar_paragraphs) - m_arShapes.push_back(CreateSingleParagraphShape(p)); - } + return ar_paragraphs; } std::shared_ptr CPage::CreateSingleLineShape(std::shared_ptr& pLine) diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index cf1b632f52..29d00c251f 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -26,12 +26,13 @@ namespace NSDocxRenderer }; double m_dWidth {0.0}; - double m_dHeight {0.0}; + double m_dHeight{0.0}; LONG m_lCurrentCommand{0}; - LONG m_lClipMode{0}; + LONG m_lClipMode {0}; TextAssociationType m_eTextAssociationType{TextAssociationType::tatPlainParagraph}; + NSFonts::IApplicationFonts* m_pAppFonts{nullptr}; NSStructures::CFont m_oFont; @@ -46,13 +47,14 @@ namespace NSDocxRenderer CVectorGraphics m_oCurrVectorGraphics, m_oClipVectorGraphics; CContTextBuilder m_oContBuilder; - std::vector> m_arConts; - std::vector> m_arTextLines; - std::vector> m_arDiacriticalSymbols; - std::vector> m_arShapes; + std::vector> m_arConts; + std::vector> m_arTextLines; + std::vector> m_arDiacriticalSymbols; + std::vector> m_arShapes; + std::vector> m_arParagraphs; - std::vector m_arCompleteObjectsXml; std::vector> m_arOutputObjects; + std::vector m_arCompleteObjectsXml; bool m_bIsDeleteTextClipPage{true}; bool m_bIsRecalcFontSize {true}; @@ -67,7 +69,6 @@ namespace NSDocxRenderer void EndCommand(DWORD lType); void Clear(); - void DeleteTextClipPage(); void WriteImage(const std::shared_ptr pInfo, double& fX, double& fY, double& fWidth, double& fHeight); @@ -77,8 +78,8 @@ namespace NSDocxRenderer void PathStart(); void PathEnd(); void PathClose(); - void DrawPath(LONG lType, const std::shared_ptr pInfo); + void AddText( const PUINT pUnicodes, const PUINT pGids, @@ -94,37 +95,74 @@ namespace NSDocxRenderer void ReorderShapesForPptx(); private: - void BuildDiacriticalSymbols(); - void BuildTextLines(); + // returns std::vector of conts with diac. symbols and remove it from m_arConts + std::vector> MoveDiacriticalSymbols(); + + // returns std::vector of text lines builded from m_arConts + std::vector> BuildTextLines(); + + // returns std::vector of paragraphs builded from m_arTextLines + std::vector> BuildParagraphs(); + + // returns std::vector of base items builded from m_arParagraphs + std::vector> BuildOutputObjects(); + + // analyze shapes (set lines type) + void AnalyzeShapes(); + + // analyze type of lines (double, wave, etc.) + void AnalyzeLinesType(); + + // analyze m_arTextLines and add effects, adds diac, super-sub scripts etc. void AnalyzeTextLines(); - void SplitLines(); - void CalcSelected(); - void BuildParagraphes(); - std::vector>> GetLinesByGroups(); + // analyze drop caps (creates shapes) + void AnalyzeDropCaps(); - void MergeShapes(); - void CalcShapesRotation(); + // analyze conts in text lines + void AnalyzeConts(); // strikeouts, underlines, highlights, outline void AnalyzeEffects(); + // adds diacritical symbols in conts + void AddDiacriticalSymbols(); + + // super-sub scripts line merge + void MergeLinesByVertAlignType(); + + // remove out of bounds text lines + void DeleteTextClipPage(); + + // merging conts in text lines + void MergeConts(); + + // set dominant shapes + void DetermineDominantGraphics(); + + // split lines by graphics + void SplitLines(); + + // creates shapes from overlapping text lines + void AnalyzeOverlapLines(); + + // calc selected sizes of conts + void CalcSelected(); + + // merge shapes with each other + void MergeShapes(); + + // calc true shapes rotation for ooxml format + void CalcShapesRotation(); + + // get lines by groups by X + std::vector>> GetLinesByGroups(); + bool IsLineCrossingText(std::shared_ptr pShape, std::shared_ptr pCont); bool IsLineBelowText(std::shared_ptr pShape, std::shared_ptr pCont); bool IsHighlight(std::shared_ptr pShape, std::shared_ptr pCont); bool IsOutline(std::shared_ptr pShape, std::shared_ptr pCont); - void AnalyzeDropCaps(); - void AnalyzeConts(); - void AddDiacriticalSymbols(); - void MergeLinesByVertAlignType(); - - void AnalyzeShapes(); - void DetermineLinesType(); - - void MergeConts(); - void DetermineDominantGraphics(); - bool IsShapeBorderBetweenVertical(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept; bool IsShapeBorderBetweenHorizontal(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept; bool IsShapeBorderTrough(std::shared_ptr pItem, double& dXCrossing, double& dYCrossing) const noexcept; @@ -132,7 +170,6 @@ namespace NSDocxRenderer std::shared_ptr CreateSingleLineShape(std::shared_ptr& pLine); std::shared_ptr CreateSingleParagraphShape(std::shared_ptr& pParagraph); - // конвертим m_arImages, m_arShapes, m_arParagraphs в xml-строку void ToXml(NSStringUtils::CStringBuilder& oWriter); void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter); diff --git a/DocxRenderer/src/logic/elements/ContText.cpp b/DocxRenderer/src/logic/elements/ContText.cpp index fa18693be2..50bd7b0dc7 100644 --- a/DocxRenderer/src/logic/elements/ContText.cpp +++ b/DocxRenderer/src/logic/elements/ContText.cpp @@ -546,6 +546,11 @@ namespace NSDocxRenderer { return IsTextOnlySpaces(m_oText); } + bool CContText::IsDiacritical() const noexcept + { + const auto& text = GetText(); + return text.length() == 1 && CContText::IsUnicodeDiacriticalMark(text.at(0)); + } void CContText::AddTextBack(const NSStringUtils::CStringUTF32& oText, const std::vector& arSymWidths) { diff --git a/DocxRenderer/src/logic/elements/ContText.h b/DocxRenderer/src/logic/elements/ContText.h index ab59d10c7e..e0c582ce1f 100644 --- a/DocxRenderer/src/logic/elements/ContText.h +++ b/DocxRenderer/src/logic/elements/ContText.h @@ -117,6 +117,7 @@ namespace NSDocxRenderer bool IsDuplicate(CContText* pCont, eVerticalCrossingType eVType, eHorizontalCrossingType eHType) const noexcept; bool IsOnlySpaces() const; + bool IsDiacritical() const noexcept; double CalculateSpace() const noexcept; // check font effect and delete not needed cont @@ -154,7 +155,7 @@ namespace NSDocxRenderer CContTextBuilder(CFontStyleManager* pFontStyleManager, CFontSelector* pFontSelector); ~CContTextBuilder() = default; - // after call CContTextBuilder is empty. + // after call CContTextBuilder is empty std::vector GetConts(); void AddUnicode( double dTop, From de4897fdefb0f4554ddb46bae5ca4e49a2f8dd8e Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Fri, 13 Dec 2024 16:54:16 +0300 Subject: [PATCH 03/17] Add HorVerLinesCollector --- DocxRenderer/src/logic/Page.cpp | 103 +++++++++--------- DocxRenderer/src/logic/Page.h | 57 ++++++---- DocxRenderer/src/logic/elements/Shape.cpp | 4 +- DocxRenderer/src/logic/elements/Shape.h | 2 - DocxRenderer/src/resources/VectorGraphics.cpp | 34 ++++++ DocxRenderer/src/resources/VectorGraphics.h | 20 ++++ 6 files changed, 142 insertions(+), 78 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index bd72268654..b0e55aee7a 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -169,7 +169,7 @@ namespace NSDocxRenderer // save default image vector before clip to calc blipFill auto image_vector = m_oCurrVectorGraphics; - auto set_fill_mode = [this, lType, &transform_det] (std::shared_ptr s) { + auto set_fill_mode = [this, lType, &transform_det] (shape_ptr_t s) { if (lType & c_nStroke) { s->m_bIsNoStroke = false; @@ -419,26 +419,26 @@ namespace NSDocxRenderer auto right = MoveNullptr(m_arShapes.begin(), m_arShapes.end()); m_arShapes.erase(right, m_arShapes.end()); - std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& s1, const CShape::shape_ptr_t& s2) { + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& s1, const shape_ptr_t& s2) { if (s1->m_bIsBehindDoc && !s2->m_bIsBehindDoc) return true; if (!s1->m_bIsBehindDoc && s2->m_bIsBehindDoc) return false; return s1->m_nOrder < s2->m_nOrder; }); } - std::vector> CPage::MoveDiacriticalSymbols() + std::vector CPage::MoveDiacriticalSymbols() { - std::vector> diac_symbols; + std::vector diac_symbols; for (auto& cont : m_arConts) if (cont && cont->IsDiacritical()) diac_symbols.push_back(std::move(cont)); return diac_symbols; } - std::vector> CPage::BuildTextLines() + std::vector CPage::BuildTextLines() { - std::shared_ptr curr_line = nullptr; - std::vector> text_lines; + line_ptr_t curr_line = nullptr; + std::vector text_lines; for (auto& cont : m_arConts) { @@ -493,13 +493,13 @@ namespace NSDocxRenderer if (m_arShapes.empty()) return; - std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& a, const CShape::shape_ptr_t& b) { + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& a, const shape_ptr_t& b) { if (!a) return false; if (!b) return true; return a->m_nOrder < b->m_nOrder; }); - using shape_ref_ptr_t = std::reference_wrapper>; + using shape_ref_ptr_t = std::reference_wrapper; for (size_t i = 0; i < m_arShapes.size() - 1; i++) { shape_ref_ptr_t val = m_arShapes[i]; @@ -520,9 +520,9 @@ namespace NSDocxRenderer } } - std::vector> CPage::BuildOutputObjects() + std::vector CPage::BuildOutputObjects() { - std::vector> output_objects; + std::vector output_objects; if (m_eTextAssociationType == TextAssociationType::tatPlainParagraph || m_eTextAssociationType == TextAssociationType::tatPlainLine) @@ -594,15 +594,16 @@ namespace NSDocxRenderer void CPage::AnalyzeShapes() { + std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const shape_ptr_t& a, const shape_ptr_t& b) { + return a->m_dLeft < b->m_dLeft; + }); + AnalyzeLinesType(); + GetHorVerLines(); } void CPage::AnalyzeLinesType() { - std::sort(m_arShapes.begin(), m_arShapes.end(), [] (const CShape::shape_ptr_t& a, const CShape::shape_ptr_t& b) { - return a->m_dLeft < b->m_dLeft; - }); - for (size_t i = 0; i < m_arShapes.size(); ++i) { if (!m_arShapes[i] || m_arShapes[i]->m_dHeight > c_dMAX_LINE_HEIGHT_MM || // рассматриваем только тонкие объекты @@ -659,10 +660,16 @@ namespace NSDocxRenderer } } + void CPage::GetHorVerLines() + { + for (const auto& shape : m_arShapes) + if (shape) + m_oHorVerLinesCollector.AddVector(shape->m_oVector); + } + void CPage::AnalyzeTextLines() { // вся логика основана на отсортированных списках объектов - using line_ptr_t = std::shared_ptr; std::sort(m_arTextLines.begin(), m_arTextLines.end(), [] (const line_ptr_t& a, const line_ptr_t& b) { return a->m_dBaselinePos < b->m_dBaselinePos; }); @@ -681,7 +688,6 @@ namespace NSDocxRenderer auto right = MoveNullptr(m_arTextLines.begin(), m_arTextLines.end()); m_arTextLines.erase(right, m_arTextLines.end()); - using line_ptr_t = std::shared_ptr; std::sort(m_arTextLines.begin(), m_arTextLines.end(), [] (const line_ptr_t& a, const line_ptr_t& b) { return a->m_dBaselinePos < b->m_dBaselinePos; }); @@ -691,8 +697,8 @@ namespace NSDocxRenderer { double avg_font_size = m_oManagers.pParagraphStyleManager->GetAvgFontSize(); - std::vector&, std::shared_ptr&>> possible_caps; - std::vector> drop_caps; + std::vector> possible_caps; + std::vector drop_caps; for (size_t i = 0; i < m_arTextLines.size(); i++) { @@ -853,7 +859,7 @@ namespace NSDocxRenderer for (size_t k = 0; k < curr_line->m_arConts.size(); ++k) { - std::shared_ptr curr_cont = curr_line->m_arConts[k]; + cont_ptr_t curr_cont = curr_line->m_arConts[k]; if (!curr_cont) continue; @@ -936,7 +942,7 @@ namespace NSDocxRenderer } } - bool CPage::IsLineCrossingText(std::shared_ptr pShape, std::shared_ptr pCont) + bool CPage::IsLineCrossingText(shape_ptr_t pShape, cont_ptr_t pCont) { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); double dTopBorder = pCont->m_dTop + pCont->m_dHeight / 3; @@ -961,7 +967,7 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4; } - bool CPage::IsLineBelowText(std::shared_ptr pShape, std::shared_ptr pCont) + bool CPage::IsLineBelowText(shape_ptr_t pShape, cont_ptr_t pCont) { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); bool bIf1 = (pShape->m_eGraphicsType == eGraphicsType::gtRectangle || @@ -985,7 +991,7 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4; } - bool CPage::IsHighlight(std::shared_ptr pShape, std::shared_ptr pCont) + bool CPage::IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont) { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); @@ -1015,7 +1021,7 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4 && !bIf5 && bIf6 && bIf7; } - bool CPage::IsOutline(std::shared_ptr pShape, std::shared_ptr pCont) + bool CPage::IsOutline(shape_ptr_t pShape, cont_ptr_t pCont) { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); auto v_type = pCont->CBaseItem::GetVerticalCrossingType(pShape.get()); @@ -1101,7 +1107,7 @@ namespace NSDocxRenderer if (line->m_eVertAlignType == eVertAlignType::vatSuperscript || line->m_eVertAlignType == eVertAlignType::vatSubscript) { - std::shared_ptr& base_line = line->m_pLine; + line_ptr_t& base_line = line->m_pLine; if (base_line) { for (auto& pCont : line->m_arConts) @@ -1160,7 +1166,7 @@ namespace NSDocxRenderer void CPage::DetermineDominantGraphics() { - std::shared_ptr pDominantShape = nullptr; + shape_ptr_t pDominantShape = nullptr; for (size_t i = 0; i < m_arTextLines.size(); ++i) { @@ -1194,14 +1200,14 @@ namespace NSDocxRenderer } } - bool CPage::IsShapeBorderBetweenVertical(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept + bool CPage::IsShapeBorderBetweenVertical(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept { double left = std::min(pFirst->m_dRight, pSecond->m_dRight); double right = std::max(pFirst->m_dLeft, pSecond->m_dLeft); double top = std::min(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); double bot = std::max(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); - std::shared_ptr dummy_cont = std::make_shared(); + auto dummy_cont = std::make_shared(); dummy_cont->m_dLeft = left; dummy_cont->m_dRight = right; dummy_cont->m_dTopWithAscent = top; @@ -1213,14 +1219,14 @@ namespace NSDocxRenderer return false; } - bool CPage::IsShapeBorderBetweenHorizontal(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept + bool CPage::IsShapeBorderBetweenHorizontal(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept { double left = std::min(pFirst->m_dLeft, pSecond->m_dLeft); double right = std::max(pFirst->m_dRight, pSecond->m_dRight); double top = std::min(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); double bot = std::max(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); - std::shared_ptr dummy_cont = std::make_shared(); + auto dummy_cont = std::make_shared(); dummy_cont->m_dLeft = left; dummy_cont->m_dRight = right; dummy_cont->m_dTopWithAscent = top; @@ -1232,7 +1238,7 @@ namespace NSDocxRenderer return false; } - bool CPage::IsShapeBorderTrough(std::shared_ptr pItem, double& dXCrossing, double& dYCrossing) const noexcept + bool CPage::IsShapeBorderTrough(cont_ptr_t pItem, double& dXCrossing, double& dYCrossing) const noexcept { double left = pItem->m_dLeft; double right = pItem->m_dRight; @@ -1303,8 +1309,8 @@ namespace NSDocxRenderer || (is_space && is_cont_wide) || is_shape_trough) { - std::vector> line_conts_first; - std::vector> line_conts_second; + std::vector line_conts_first; + std::vector line_conts_second; // taking last cont or not for (size_t j = 0; j < (is_space ? i : i + 1); ++j) @@ -1315,8 +1321,8 @@ namespace NSDocxRenderer if (line->m_arConts[j]) line_conts_second.push_back(line->m_arConts[j]); - std::shared_ptr line_first(new CTextLine()); - std::shared_ptr line_second(new CTextLine()); + line_ptr_t line_first(new CTextLine()); + line_ptr_t line_second(new CTextLine()); line_first->AddConts(line_conts_first); line_second->AddConts(line_conts_second); @@ -1341,7 +1347,7 @@ namespace NSDocxRenderer } } - std::vector>> CPage::GetLinesByGroups() + std::vector> CPage::GetLinesByGroups() { struct Group { double left{}; @@ -1351,7 +1357,7 @@ namespace NSDocxRenderer bool closed{false}; }; - std::vector>> line_groups; + std::vector> line_groups; std::vector groups; for (auto& line : m_arTextLines) @@ -1405,7 +1411,7 @@ namespace NSDocxRenderer new_group.closed = false; groups.push_back(new_group); - std::vector> line_group; + std::vector line_group; line_group.push_back(line); line_groups.push_back(line_group); } @@ -1461,13 +1467,13 @@ namespace NSDocxRenderer } } - std::vector> CPage::BuildParagraphs() + std::vector CPage::BuildParagraphs() { if (m_arTextLines.empty()) return {}; auto line_groups = GetLinesByGroups(); - std::vector> ar_paragraphs; + std::vector ar_paragraphs; double min_left{m_dWidth}; double max_right{0.0}; @@ -1480,7 +1486,7 @@ namespace NSDocxRenderer }; // lamda to setup and add paragpraph - auto add_paragraph = [this, &max_right, &min_left, &ar_paragraphs] (std::shared_ptr& paragraph) { + auto add_paragraph = [this, &max_right, &min_left, &ar_paragraphs] (paragraph_ptr_t& paragraph) { paragraph->m_dBaselinePos = paragraph->m_arLines.back()->m_dBaselinePos; paragraph->m_dTop = paragraph->m_arLines.front()->m_dTop; @@ -1557,13 +1563,13 @@ namespace NSDocxRenderer }; // lamda to add line and setup min_left/max_right - auto add_line = [&min_left, &max_right] (std::shared_ptr& paragraph, const std::shared_ptr& curr_line) { + auto add_line = [&min_left, &max_right] (paragraph_ptr_t& paragraph, const line_ptr_t& curr_line) { min_left = std::min(min_left, curr_line->m_dLeft); max_right = std::max(max_right, curr_line->m_dRight); paragraph->m_arLines.push_back(curr_line); }; - auto build_paragraphs = [this, add_line, add_paragraph] (const std::vector>& text_lines) { + auto build_paragraphs = [this, add_line, add_paragraph] (const std::vector& text_lines) { // ar_spacing[index]- расстояние строки до строки снизу // если 0.0 - строка последняя std::vector ar_spacings(text_lines.size(), 0.0); @@ -1746,7 +1752,7 @@ namespace NSDocxRenderer continue; } - std::shared_ptr cont = line_bot->m_arConts[0]; + cont_ptr_t cont = line_bot->m_arConts[0]; double line_with_first_right = line_top->m_dRight + line_bot->m_dFirstWordWidth; double line_with_first_left = line_top->m_dLeft - line_bot->m_dFirstWordWidth; @@ -1815,7 +1821,6 @@ namespace NSDocxRenderer build_paragraphs(g); } - using paragraph_ptr_t = std::shared_ptr; std::sort(ar_paragraphs.begin(), ar_paragraphs.end(), [] (const paragraph_ptr_t& a, const paragraph_ptr_t& b) { return a->m_dBaselinePos < b->m_dBaselinePos; }); @@ -1823,7 +1828,7 @@ namespace NSDocxRenderer return ar_paragraphs; } - std::shared_ptr CPage::CreateSingleLineShape(std::shared_ptr& pLine) + CPage::shape_ptr_t CPage::CreateSingleLineShape(line_ptr_t& pLine) { auto pParagraph = std::make_shared(); @@ -1858,11 +1863,9 @@ namespace NSDocxRenderer return pShape; } - std::shared_ptr CPage::CreateSingleParagraphShape(std::shared_ptr& pParagraph) + CPage::shape_ptr_t CPage::CreateSingleParagraphShape(paragraph_ptr_t& pParagraph) { - std::shared_ptr pShape; - - pShape = std::make_shared(); + auto pShape = std::make_shared(); pShape->m_dLeft = pParagraph->m_dLeft; pShape->m_dTop = pParagraph->m_dTop; diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index 29d00c251f..896211a22c 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -25,6 +25,12 @@ namespace NSDocxRenderer CFontSelector* pFontSelector; }; + using shape_ptr_t = std::shared_ptr; + using cont_ptr_t = std::shared_ptr; + using line_ptr_t = std::shared_ptr; + using item_ptr_t = std::shared_ptr; + using paragraph_ptr_t = std::shared_ptr; + double m_dWidth {0.0}; double m_dHeight{0.0}; @@ -45,16 +51,18 @@ namespace NSDocxRenderer CManagers m_oManagers; CVectorGraphics m_oCurrVectorGraphics, m_oClipVectorGraphics; - CContTextBuilder m_oContBuilder; - std::vector> m_arConts; - std::vector> m_arTextLines; - std::vector> m_arDiacriticalSymbols; - std::vector> m_arShapes; - std::vector> m_arParagraphs; + CContTextBuilder m_oContBuilder; + CHorVerLinesCollector m_oHorVerLinesCollector; - std::vector> m_arOutputObjects; - std::vector m_arCompleteObjectsXml; + std::vector m_arConts; + std::vector m_arTextLines; + std::vector m_arDiacriticalSymbols; + std::vector m_arShapes; + std::vector m_arParagraphs; + + std::vector m_arOutputObjects; + std::vector m_arCompleteObjectsXml; bool m_bIsDeleteTextClipPage{true}; bool m_bIsRecalcFontSize {true}; @@ -96,16 +104,16 @@ namespace NSDocxRenderer private: // returns std::vector of conts with diac. symbols and remove it from m_arConts - std::vector> MoveDiacriticalSymbols(); + std::vector MoveDiacriticalSymbols(); // returns std::vector of text lines builded from m_arConts - std::vector> BuildTextLines(); + std::vector BuildTextLines(); // returns std::vector of paragraphs builded from m_arTextLines - std::vector> BuildParagraphs(); + std::vector BuildParagraphs(); // returns std::vector of base items builded from m_arParagraphs - std::vector> BuildOutputObjects(); + std::vector BuildOutputObjects(); // analyze shapes (set lines type) void AnalyzeShapes(); @@ -113,6 +121,9 @@ namespace NSDocxRenderer // analyze type of lines (double, wave, etc.) void AnalyzeLinesType(); + // get horizontal and vertical lines from shapes + void GetHorVerLines(); + // analyze m_arTextLines and add effects, adds diac, super-sub scripts etc. void AnalyzeTextLines(); @@ -140,7 +151,7 @@ namespace NSDocxRenderer // set dominant shapes void DetermineDominantGraphics(); - // split lines by graphics + // split lines by graphics TODO: rewrite with horverlinescollector void SplitLines(); // creates shapes from overlapping text lines @@ -156,19 +167,19 @@ namespace NSDocxRenderer void CalcShapesRotation(); // get lines by groups by X - std::vector>> GetLinesByGroups(); + std::vector> GetLinesByGroups(); - bool IsLineCrossingText(std::shared_ptr pShape, std::shared_ptr pCont); - bool IsLineBelowText(std::shared_ptr pShape, std::shared_ptr pCont); - bool IsHighlight(std::shared_ptr pShape, std::shared_ptr pCont); - bool IsOutline(std::shared_ptr pShape, std::shared_ptr pCont); + bool IsLineCrossingText(shape_ptr_t pShape, cont_ptr_t pCont); + bool IsLineBelowText(shape_ptr_t pShape, cont_ptr_t pCont); + bool IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont); + bool IsOutline(shape_ptr_t pShape, cont_ptr_t pCont); - bool IsShapeBorderBetweenVertical(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept; - bool IsShapeBorderBetweenHorizontal(std::shared_ptr pFirst, std::shared_ptr pSecond) const noexcept; - bool IsShapeBorderTrough(std::shared_ptr pItem, double& dXCrossing, double& dYCrossing) const noexcept; + bool IsShapeBorderBetweenVertical(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; + bool IsShapeBorderBetweenHorizontal(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; + bool IsShapeBorderTrough(cont_ptr_t pItem, double& dXCrossing, double& dYCrossing) const noexcept; - std::shared_ptr CreateSingleLineShape(std::shared_ptr& pLine); - std::shared_ptr CreateSingleParagraphShape(std::shared_ptr& pParagraph); + shape_ptr_t CreateSingleLineShape(line_ptr_t& pLine); + shape_ptr_t CreateSingleParagraphShape(paragraph_ptr_t& pParagraph); void ToXml(NSStringUtils::CStringBuilder& oWriter); void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter); diff --git a/DocxRenderer/src/logic/elements/Shape.cpp b/DocxRenderer/src/logic/elements/Shape.cpp index 4b31f34fdf..103faa4d6b 100644 --- a/DocxRenderer/src/logic/elements/Shape.cpp +++ b/DocxRenderer/src/logic/elements/Shape.cpp @@ -323,7 +323,7 @@ namespace NSDocxRenderer return; // линия должна быть одного размера по высоте } - auto set_line_type = [] (shape_ptr_t& master, shape_ptr_t& slave, eLineType type) { + auto set_line_type = [] (std::shared_ptr& master, std::shared_ptr& slave, eLineType type) { master->m_eLineType = type; master->RecalcWithNewItem(slave.get()); master->m_oVector.Join(std::move(slave->m_oVector)); @@ -1017,6 +1017,4 @@ namespace NSDocxRenderer } oWriter.WriteString(L""); } - - }; // namespace NSDocxRenderer diff --git a/DocxRenderer/src/logic/elements/Shape.h b/DocxRenderer/src/logic/elements/Shape.h index 09801bcdd7..317ac2d0e4 100644 --- a/DocxRenderer/src/logic/elements/Shape.h +++ b/DocxRenderer/src/logic/elements/Shape.h @@ -31,8 +31,6 @@ namespace NSDocxRenderer }; public: - using shape_ptr_t = std::shared_ptr; - eShapeType m_eType {eShapeType::stUnknown}; NSStructures::CBrush m_oBrush{}; diff --git a/DocxRenderer/src/resources/VectorGraphics.cpp b/DocxRenderer/src/resources/VectorGraphics.cpp index 0205f63a84..382ea49ab3 100644 --- a/DocxRenderer/src/resources/VectorGraphics.cpp +++ b/DocxRenderer/src/resources/VectorGraphics.cpp @@ -390,4 +390,38 @@ namespace NSDocxRenderer return points; } + std::vector> CHorVerLinesCollector::GetHorizontal() + { + return std::move(m_arHorizontal); + } + std::vector> CHorVerLinesCollector::GetVertical() + { + return std::move(m_arVertical); + } + + void CHorVerLinesCollector::AddVector(const CVectorGraphics& oVector) + { + double last_x{}; + double last_y{}; + + for (const auto& command : oVector.GetData()) + { + if (command.type == CVectorGraphics::ePathCommandType::pctLine) + { + double x = command.points.front().x; + double y = command.points.front().y; + + if (x - last_x <= std::numeric_limits::epsilon()) + m_arVertical.push_back({last_y, y}); + + else if (y - last_y <= std::numeric_limits::epsilon()) + m_arHorizontal.push_back({last_x, x}); + } + if (!command.points.empty()) + { + last_x = command.points.back().x; + last_y = command.points.back().y; + } + } + } } diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index ea29b12546..bbb4f2a68a 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -96,4 +96,24 @@ namespace NSDocxRenderer static Aggplus::BooleanOpType GetOpType(long nClipType); static std::vector GetPointsCurve(const std::array& curve, double step = 0.05); }; + + // collect and contains horizontal and vertical lines + class CHorVerLinesCollector + { + public: + CHorVerLinesCollector() = default; + ~CHorVerLinesCollector() = default; + + // after call m_arHorizontal is empty + std::vector> GetHorizontal(); + + // after call m_arVertical is empty + std::vector> GetVertical(); + + void AddVector(const CVectorGraphics& oVector); + + private: + std::vector> m_arHorizontal; + std::vector> m_arVertical; + }; } From 2f2d11a5f6317a70d9b269935ae01ec608e5d389 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Sat, 14 Dec 2024 06:51:59 +0300 Subject: [PATCH 04/17] Fix bug with recalc size of space --- DocxRenderer/src/logic/Page.cpp | 2 +- DocxRenderer/src/logic/Page.h | 8 ++++---- DocxRenderer/src/logic/elements/ContText.cpp | 9 +++++++-- DocxRenderer/src/resources/VectorGraphics.cpp | 13 +++++++++---- DocxRenderer/src/resources/VectorGraphics.h | 5 +++-- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index b0e55aee7a..93c96fac6b 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -599,7 +599,6 @@ namespace NSDocxRenderer }); AnalyzeLinesType(); - GetHorVerLines(); } void CPage::AnalyzeLinesType() @@ -681,6 +680,7 @@ namespace NSDocxRenderer MergeLinesByVertAlignType(); DeleteTextClipPage(); MergeConts(); + GetHorVerLines(); SplitLines(); AnalyzeOverlapLines(); diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index 896211a22c..a5e74ea338 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -121,9 +121,6 @@ namespace NSDocxRenderer // analyze type of lines (double, wave, etc.) void AnalyzeLinesType(); - // get horizontal and vertical lines from shapes - void GetHorVerLines(); - // analyze m_arTextLines and add effects, adds diac, super-sub scripts etc. void AnalyzeTextLines(); @@ -148,10 +145,13 @@ namespace NSDocxRenderer // merging conts in text lines void MergeConts(); + // get horizontal and vertical lines from shapes + void GetHorVerLines(); + // set dominant shapes void DetermineDominantGraphics(); - // split lines by graphics TODO: rewrite with horverlinescollector + // split lines by graphics void SplitLines(); // creates shapes from overlapping text lines diff --git a/DocxRenderer/src/logic/elements/ContText.cpp b/DocxRenderer/src/logic/elements/ContText.cpp index 50bd7b0dc7..1abb30be1e 100644 --- a/DocxRenderer/src/logic/elements/ContText.cpp +++ b/DocxRenderer/src/logic/elements/ContText.cpp @@ -108,8 +108,13 @@ namespace NSDocxRenderer double dBoxWidth; double dBoxHeight; - m_pManager->SetStringGid(0); - m_pManager->MeasureString(m_oText.ToStdWString(), 0, 0, dBoxX, dBoxY, dBoxWidth, dBoxHeight, CFontManager::mtPosition); + if (m_oText.ToStdWString() == L" ") + dBoxWidth = m_pManager->GetSpaceWidthMM(); + else + { + m_pManager->SetStringGid(0); + m_pManager->MeasureString(m_oText.ToStdWString(), 0, 0, dBoxX, dBoxY, dBoxWidth, dBoxHeight, CFontManager::mtPosition); + } m_oSelectedSizes.dWidth = dBoxWidth; m_oSelectedSizes.dHeight = dBoxHeight; diff --git a/DocxRenderer/src/resources/VectorGraphics.cpp b/DocxRenderer/src/resources/VectorGraphics.cpp index 382ea49ab3..2ffed33f1e 100644 --- a/DocxRenderer/src/resources/VectorGraphics.cpp +++ b/DocxRenderer/src/resources/VectorGraphics.cpp @@ -390,13 +390,13 @@ namespace NSDocxRenderer return points; } - std::vector> CHorVerLinesCollector::GetHorizontal() + const std::vector>& CHorVerLinesCollector::GetHorizontal() { - return std::move(m_arHorizontal); + return m_arHorizontal; } - std::vector> CHorVerLinesCollector::GetVertical() + const std::vector>& CHorVerLinesCollector::GetVertical() { - return std::move(m_arVertical); + return m_arVertical; } void CHorVerLinesCollector::AddVector(const CVectorGraphics& oVector) @@ -424,4 +424,9 @@ namespace NSDocxRenderer } } } + void CHorVerLinesCollector::Clear() + { + m_arVertical.clear(); + m_arHorizontal.clear(); + } } diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index bbb4f2a68a..f0a0a0c556 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -105,12 +105,13 @@ namespace NSDocxRenderer ~CHorVerLinesCollector() = default; // after call m_arHorizontal is empty - std::vector> GetHorizontal(); + const std::vector>& GetHorizontal(); // after call m_arVertical is empty - std::vector> GetVertical(); + const std::vector>& GetVertical(); void AddVector(const CVectorGraphics& oVector); + void Clear(); private: std::vector> m_arHorizontal; From b125c19d02465235278501aad9ebfd714b967614 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Sat, 14 Dec 2024 07:13:48 +0300 Subject: [PATCH 05/17] Remove useless call --- DocxRenderer/src/logic/elements/TextLine.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/DocxRenderer/src/logic/elements/TextLine.cpp b/DocxRenderer/src/logic/elements/TextLine.cpp index d9aa6f5eca..5af0ec5af6 100644 --- a/DocxRenderer/src/logic/elements/TextLine.cpp +++ b/DocxRenderer/src/logic/elements/TextLine.cpp @@ -97,9 +97,6 @@ namespace NSDocxRenderer wide_space->m_pFontStyle = pFirst->m_pFontStyle; wide_space->m_pShape = nullptr; wide_space->m_iNumDuplicates = 0; - - // cache that value? (calls rarely) - wide_space->CalcSelected(); }; if (bIsEqual) From 20d2ff7954ee0d275edf97ce4524254863993feb Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Sat, 14 Dec 2024 11:18:42 +0300 Subject: [PATCH 06/17] Refactoring --- DocxRenderer/DocxRenderer.cpp | 35 +------- DocxRenderer/src/logic/Page.cpp | 52 +++++++++-- DocxRenderer/src/logic/Page.h | 95 +++++++++++---------- DocxRenderer/src/resources/VectorGraphics.h | 3 - 4 files changed, 99 insertions(+), 86 deletions(-) diff --git a/DocxRenderer/DocxRenderer.cpp b/DocxRenderer/DocxRenderer.cpp index bef210f8b2..740f66beac 100644 --- a/DocxRenderer/DocxRenderer.cpp +++ b/DocxRenderer/DocxRenderer.cpp @@ -126,20 +126,7 @@ std::vector CDocxRenderer::ScanPage(IOfficeDrawingFile* pFile, siz DrawPage(pFile, nPage); - std::vector xml_shapes; - for (const auto& shape : m_pInternal->m_oDocument.m_oCurrentPage.m_arShapes) - { - if (!shape) continue; - auto writer = new NSStringUtils::CStringBuilder(); - shape->ToXml(*writer); - xml_shapes.push_back(writer->GetData()); - delete writer; - } - - std::vector& arComleteObjects = m_pInternal->m_oDocument.m_oCurrentPage.m_arCompleteObjectsXml; - if (!arComleteObjects.empty()) - xml_shapes.insert(xml_shapes.end(), arComleteObjects.begin(), arComleteObjects.end()); - + auto xml_shapes = m_pInternal->m_oDocument.m_oCurrentPage.GetXmlShapes(); m_pInternal->m_oDocument.Clear(); return xml_shapes; } @@ -154,23 +141,7 @@ std::vector CDocxRenderer::ScanPagePptx(IOfficeDrawingFile* pFile, DrawPage(pFile, nPage); - // for drawingml is no tag behind-doc - so we need to reorder shapes - m_pInternal->m_oDocument.m_oCurrentPage.ReorderShapesForPptx(); - - std::vector xml_shapes; - for (const auto& shape : m_pInternal->m_oDocument.m_oCurrentPage.m_arShapes) - { - if (!shape) continue; - auto writer = new NSStringUtils::CStringBuilder(); - shape->ToXmlPptx(*writer); - xml_shapes.push_back(writer->GetData()); - delete writer; - } - - std::vector& arComleteObjects = m_pInternal->m_oDocument.m_oCurrentPage.m_arCompleteObjectsXml; - if (!arComleteObjects.empty()) - xml_shapes.insert(xml_shapes.end(), arComleteObjects.begin(), arComleteObjects.end()); - + auto xml_shapes = m_pInternal->m_oDocument.m_oCurrentPage.GetXmlShapesPptx(); m_pInternal->m_oDocument.Clear(); return xml_shapes; } @@ -241,7 +212,7 @@ HRESULT CDocxRenderer::AdvancedCommand(IAdvancedCommand* command) std::string sNewId = "r:embed=\"rId" + std::to_string(pInfo->m_nId + c_iStartingIdForImages) + "\""; NSStringUtils::string_replaceA(sUtf8Shape, "r:embed=\"\"", sNewId); } - m_pInternal->m_oDocument.m_oCurrentPage.m_arCompleteObjectsXml.push_back(UTF8_TO_U(sUtf8Shape)); + m_pInternal->m_oDocument.m_oCurrentPage.AddCompleteXml(UTF8_TO_U(sUtf8Shape)); return S_OK; } case IAdvancedCommand::AdvancedCommandType::ShapeEnd: diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 93c96fac6b..2aef825cdc 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -54,6 +54,7 @@ namespace NSDocxRenderer m_oEdgeText.SetDefaultParams(); m_oTransform.Reset(); + m_oHorVerLinesCollector.Clear(); m_arConts.clear(); m_arTextLines.clear(); m_arDiacriticalSymbols.clear(); @@ -413,6 +414,45 @@ namespace NSDocxRenderer ToXml(oWriter); WriteSectionToFile(bIsLastPage, oWriter); } + + std::vector CPage::GetXmlShapes() + { + std::vector xml_shapes; + for (const auto& shape : m_arShapes) + { + if (!shape) continue; + auto writer = new NSStringUtils::CStringBuilder(); + shape->ToXml(*writer); + xml_shapes.push_back(writer->GetData()); + delete writer; + } + if (!m_arCompleteObjectsXml.empty()) + xml_shapes.insert(xml_shapes.end(), m_arCompleteObjectsXml.begin(), m_arCompleteObjectsXml.end()); + + return xml_shapes; + } + std::vector CPage::GetXmlShapesPptx() + { + ReorderShapesForPptx(); + + std::vector xml_shapes; + for (const auto& shape : m_arShapes) + { + if (!shape) continue; + auto writer = new NSStringUtils::CStringBuilder(); + shape->ToXmlPptx(*writer); + xml_shapes.push_back(writer->GetData()); + delete writer; + } + if (!m_arCompleteObjectsXml.empty()) + xml_shapes.insert(xml_shapes.end(), m_arCompleteObjectsXml.begin(), m_arCompleteObjectsXml.end()); + + return xml_shapes; + } + void CPage::AddCompleteXml(const std::wstring oXml) + { + m_arCompleteObjectsXml.push_back(oXml); + } void CPage::ReorderShapesForPptx() { // переместим nullptr в конец и удалим @@ -942,7 +982,7 @@ namespace NSDocxRenderer } } - bool CPage::IsLineCrossingText(shape_ptr_t pShape, cont_ptr_t pCont) + bool CPage::IsLineCrossingText(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); double dTopBorder = pCont->m_dTop + pCont->m_dHeight / 3; @@ -967,7 +1007,7 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4; } - bool CPage::IsLineBelowText(shape_ptr_t pShape, cont_ptr_t pCont) + bool CPage::IsLineBelowText(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); bool bIf1 = (pShape->m_eGraphicsType == eGraphicsType::gtRectangle || @@ -991,7 +1031,7 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4; } - bool CPage::IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont) + bool CPage::IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); @@ -1021,7 +1061,7 @@ namespace NSDocxRenderer return bIf1 && bIf2 && bIf3 && bIf4 && !bIf5 && bIf6 && bIf7; } - bool CPage::IsOutline(shape_ptr_t pShape, cont_ptr_t pCont) + bool CPage::IsOutline(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept { auto h_type = pCont->CBaseItem::GetHorizontalCrossingType(pShape.get()); auto v_type = pCont->CBaseItem::GetVerticalCrossingType(pShape.get()); @@ -1129,7 +1169,7 @@ namespace NSDocxRenderer } } - void CPage::ToXml(NSStringUtils::CStringBuilder& oWriter) + void CPage::ToXml(NSStringUtils::CStringBuilder& oWriter) const noexcept { bool bIsNeedWP = !m_arShapes.empty(); @@ -1893,7 +1933,7 @@ namespace NSDocxRenderer return pShape; } - void CPage::WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter) + void CPage::WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter) const noexcept { // section int lWidthDx = (int)(m_dWidth * c_dMMToDx); diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index a5e74ea338..399560f95f 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -18,51 +18,27 @@ namespace NSDocxRenderer CManagers(const CManagers& other) = default; ~CManagers() = default; - CImageManager* pImageManager; - CFontStyleManager* pFontStyleManager; - CParagraphStyleManager* pParagraphStyleManager; - CFontManager* pFontManager; - CFontSelector* pFontSelector; + CImageManager* pImageManager; + CFontStyleManager* pFontStyleManager; + CParagraphStyleManager* pParagraphStyleManager; + CFontManager* pFontManager; + CFontSelector* pFontSelector; }; - using shape_ptr_t = std::shared_ptr; - using cont_ptr_t = std::shared_ptr; - using line_ptr_t = std::shared_ptr; - using item_ptr_t = std::shared_ptr; - using paragraph_ptr_t = std::shared_ptr; - double m_dWidth {0.0}; double m_dHeight{0.0}; LONG m_lCurrentCommand{0}; LONG m_lClipMode {0}; - TextAssociationType m_eTextAssociationType{TextAssociationType::tatPlainParagraph}; - + TextAssociationType m_eTextAssociationType{TextAssociationType::tatPlainParagraph}; NSFonts::IApplicationFonts* m_pAppFonts{nullptr}; - - NSStructures::CFont m_oFont; - NSStructures::CPen m_oPen; - NSStructures::CBrush m_oBrush; - NSStructures::CShadow m_oShadow; - NSStructures::CEdgeText m_oEdgeText; - - Aggplus::CMatrix m_oTransform; - CManagers m_oManagers; - - CVectorGraphics m_oCurrVectorGraphics, m_oClipVectorGraphics; - - CContTextBuilder m_oContBuilder; - CHorVerLinesCollector m_oHorVerLinesCollector; - - std::vector m_arConts; - std::vector m_arTextLines; - std::vector m_arDiacriticalSymbols; - std::vector m_arShapes; - std::vector m_arParagraphs; - - std::vector m_arOutputObjects; - std::vector m_arCompleteObjectsXml; + NSStructures::CFont m_oFont{}; + NSStructures::CPen m_oPen{}; + NSStructures::CBrush m_oBrush{}; + NSStructures::CShadow m_oShadow{}; + NSStructures::CEdgeText m_oEdgeText{}; + Aggplus::CMatrix m_oTransform{}; bool m_bIsDeleteTextClipPage{true}; bool m_bIsRecalcFontSize {true}; @@ -100,9 +76,18 @@ namespace NSDocxRenderer void Analyze(); void Record(NSStringUtils::CStringBuilder& oWriter, bool bIsLastPage); - void ReorderShapesForPptx(); + + std::vector GetXmlShapes(); + std::vector GetXmlShapesPptx(); + void AddCompleteXml(const std::wstring oXml); private: + using shape_ptr_t = std::shared_ptr; + using cont_ptr_t = std::shared_ptr; + using line_ptr_t = std::shared_ptr; + using item_ptr_t = std::shared_ptr; + using paragraph_ptr_t = std::shared_ptr; + // returns std::vector of conts with diac. symbols and remove it from m_arConts std::vector MoveDiacriticalSymbols(); @@ -166,23 +151,43 @@ namespace NSDocxRenderer // calc true shapes rotation for ooxml format void CalcShapesRotation(); + // for drawingml is no tag behind-doc - so we need to reorder shapes + void ReorderShapesForPptx(); + // get lines by groups by X std::vector> GetLinesByGroups(); - bool IsLineCrossingText(shape_ptr_t pShape, cont_ptr_t pCont); - bool IsLineBelowText(shape_ptr_t pShape, cont_ptr_t pCont); - bool IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont); - bool IsOutline(shape_ptr_t pShape, cont_ptr_t pCont); + bool IsLineCrossingText(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept; + bool IsLineBelowText(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept; + bool IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept; + bool IsOutline(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept; bool IsShapeBorderBetweenVertical(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; bool IsShapeBorderBetweenHorizontal(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; bool IsShapeBorderTrough(cont_ptr_t pItem, double& dXCrossing, double& dYCrossing) const noexcept; - shape_ptr_t CreateSingleLineShape(line_ptr_t& pLine); - shape_ptr_t CreateSingleParagraphShape(paragraph_ptr_t& pParagraph); + void ToXml(NSStringUtils::CStringBuilder& oWriter) const noexcept; + void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter) const noexcept; - void ToXml(NSStringUtils::CStringBuilder& oWriter); - void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter); + static shape_ptr_t CreateSingleLineShape(line_ptr_t& pLine); + static shape_ptr_t CreateSingleParagraphShape(paragraph_ptr_t& pParagraph); + + CManagers m_oManagers; + + CVectorGraphics m_oCurrVectorGraphics; + CVectorGraphics m_oClipVectorGraphics; + + CContTextBuilder m_oContBuilder; + CHorVerLinesCollector m_oHorVerLinesCollector; + + std::vector m_arConts; + std::vector m_arTextLines; + std::vector m_arDiacriticalSymbols; + std::vector m_arShapes; + std::vector m_arParagraphs; + + std::vector m_arOutputObjects; + std::vector m_arCompleteObjectsXml; size_t m_nShapeOrder = 0; }; diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index f0a0a0c556..bd43bebc76 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -104,10 +104,7 @@ namespace NSDocxRenderer CHorVerLinesCollector() = default; ~CHorVerLinesCollector() = default; - // after call m_arHorizontal is empty const std::vector>& GetHorizontal(); - - // after call m_arVertical is empty const std::vector>& GetVertical(); void AddVector(const CVectorGraphics& oVector); From fe2ca8c566af84ad0e5488dd23b6c3ab3da465dc Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Sat, 14 Dec 2024 11:33:47 +0300 Subject: [PATCH 07/17] Delete unused headers & add new files --- DocxRenderer/DocxRenderer.pro | 2 ++ DocxRenderer/src/logic/elements/BaseItem.h | 2 -- DocxRenderer/src/logic/elements/Table.cpp | 6 ++++++ DocxRenderer/src/logic/elements/Table.h | 15 +++++++++++++++ .../src/logic/managers/ExternalImageStorage.h | 3 +-- DocxRenderer/src/logic/managers/ImageManager.cpp | 1 + DocxRenderer/src/logic/managers/ImageManager.h | 3 +++ .../src/logic/managers/ParagraphStyleManager.h | 1 - DocxRenderer/src/resources/ColorTable.h | 1 - DocxRenderer/src/resources/VectorGraphics.cpp | 2 -- DocxRenderer/src/resources/VectorGraphics.h | 1 - 11 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 DocxRenderer/src/logic/elements/Table.cpp create mode 100644 DocxRenderer/src/logic/elements/Table.h diff --git a/DocxRenderer/DocxRenderer.pro b/DocxRenderer/DocxRenderer.pro index 1f00da46e3..5b4dc732ef 100644 --- a/DocxRenderer/DocxRenderer.pro +++ b/DocxRenderer/DocxRenderer.pro @@ -32,6 +32,7 @@ HEADERS += \ src/logic/elements/ContText.h \ src/logic/elements/Paragraph.h \ src/logic/elements/Shape.h \ + src/logic/elements/Table.h \ src/logic/elements/TextLine.h \ src/logic/managers/ExternalImageStorage.h \ src/logic/managers/FontStyleManager.h \ @@ -56,6 +57,7 @@ SOURCES += \ src/logic/elements/ContText.cpp \ src/logic/elements/Paragraph.cpp \ src/logic/elements/Shape.cpp \ + src/logic/elements/Table.cpp \ src/logic/elements/TextLine.cpp \ src/logic/managers/FontManager.cpp \ src/logic/managers/FontStyleManager.cpp \ diff --git a/DocxRenderer/src/logic/elements/BaseItem.h b/DocxRenderer/src/logic/elements/BaseItem.h index ae9f97e241..c2818ca994 100644 --- a/DocxRenderer/src/logic/elements/BaseItem.h +++ b/DocxRenderer/src/logic/elements/BaseItem.h @@ -1,6 +1,4 @@ #pragma once -#include -#include #include "../../../../DesktopEditor/common/StringBuilder.h" diff --git a/DocxRenderer/src/logic/elements/Table.cpp b/DocxRenderer/src/logic/elements/Table.cpp new file mode 100644 index 0000000000..92ab704c98 --- /dev/null +++ b/DocxRenderer/src/logic/elements/Table.cpp @@ -0,0 +1,6 @@ +#include "Table.h" + +namespace NSDocxRenderer +{ + +} // namespace NSDocxRenderer diff --git a/DocxRenderer/src/logic/elements/Table.h b/DocxRenderer/src/logic/elements/Table.h new file mode 100644 index 0000000000..8d711ee018 --- /dev/null +++ b/DocxRenderer/src/logic/elements/Table.h @@ -0,0 +1,15 @@ +#pragma once + +#include "BaseItem.h" + +namespace NSDocxRenderer +{ + class CTable : public CBaseItem + { + CTable() = default; + virtual ~CTable() = default; + }; +} // namespace NSDocxRenderer + + + diff --git a/DocxRenderer/src/logic/managers/ExternalImageStorage.h b/DocxRenderer/src/logic/managers/ExternalImageStorage.h index 1784da1a7b..77bcfd23d1 100644 --- a/DocxRenderer/src/logic/managers/ExternalImageStorage.h +++ b/DocxRenderer/src/logic/managers/ExternalImageStorage.h @@ -1,7 +1,6 @@ #pragma once -#include "../../../../DesktopEditor/raster/BgraFrame.h" +#include "../../../../DesktopEditor/graphics/Image.h" #include "../../resources/ImageInfo.h" -#include #include #ifndef DOCXRENDERER_USE_DYNAMIC_LIBRARY diff --git a/DocxRenderer/src/logic/managers/ImageManager.cpp b/DocxRenderer/src/logic/managers/ImageManager.cpp index 48c2a2b5d6..2036ea99f9 100644 --- a/DocxRenderer/src/logic/managers/ImageManager.cpp +++ b/DocxRenderer/src/logic/managers/ImageManager.cpp @@ -1,6 +1,7 @@ #include "ImageManager.h" #include "../../../../DesktopEditor/common/Directory.h" +#include "../../../../DesktopEditor/raster/BgraFrame.h" #include "../../resources/Constants.h" diff --git a/DocxRenderer/src/logic/managers/ImageManager.h b/DocxRenderer/src/logic/managers/ImageManager.h index 93ea7ac5b4..d3810fd3e1 100644 --- a/DocxRenderer/src/logic/managers/ImageManager.h +++ b/DocxRenderer/src/logic/managers/ImageManager.h @@ -1,4 +1,7 @@ #pragma once + +#include + #include "../../../../DesktopEditor/common/CalculatorCRC32.h" #include "ExternalImageStorage.h" diff --git a/DocxRenderer/src/logic/managers/ParagraphStyleManager.h b/DocxRenderer/src/logic/managers/ParagraphStyleManager.h index fce153122c..ed4d1ae182 100644 --- a/DocxRenderer/src/logic/managers/ParagraphStyleManager.h +++ b/DocxRenderer/src/logic/managers/ParagraphStyleManager.h @@ -1,6 +1,5 @@ #pragma once #include -#include #include "../elements/Paragraph.h" #include "../styles/ParagraphStyle.h" diff --git a/DocxRenderer/src/resources/ColorTable.h b/DocxRenderer/src/resources/ColorTable.h index 8ec2dc81e7..aafd08683e 100644 --- a/DocxRenderer/src/resources/ColorTable.h +++ b/DocxRenderer/src/resources/ColorTable.h @@ -1,7 +1,6 @@ #pragma once #include #include -#include class ColorTable { diff --git a/DocxRenderer/src/resources/VectorGraphics.cpp b/DocxRenderer/src/resources/VectorGraphics.cpp index 2ffed33f1e..b87b082f22 100644 --- a/DocxRenderer/src/resources/VectorGraphics.cpp +++ b/DocxRenderer/src/resources/VectorGraphics.cpp @@ -1,8 +1,6 @@ #include "VectorGraphics.h" -#include #include -#include #include #include "../../../DesktopEditor/graphics/Matrix.h" diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index bd43bebc76..6ec53346b1 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -2,7 +2,6 @@ #include "../../../DesktopEditor/graphics/GraphicsPath.h" #include -#include #include namespace NSDocxRenderer From d58424d089a60e261dc3f32b1403bca864c245df Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Sat, 14 Dec 2024 11:38:11 +0300 Subject: [PATCH 08/17] Fix build --- DocxRenderer/src/logic/elements/Shape.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DocxRenderer/src/logic/elements/Shape.h b/DocxRenderer/src/logic/elements/Shape.h index 317ac2d0e4..4a6b878672 100644 --- a/DocxRenderer/src/logic/elements/Shape.h +++ b/DocxRenderer/src/logic/elements/Shape.h @@ -1,4 +1,7 @@ #pragma once + +#include + #include "../../../../DesktopEditor/graphics/structures.h" #include "../../resources/ImageInfo.h" From 36a3b693d51056ed131eb45ee3dcb0d1b866cff3 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Tue, 17 Dec 2024 13:44:31 +0300 Subject: [PATCH 09/17] Update paragraph logic for enums --- DocxRenderer/src/logic/Page.cpp | 37 +++++++++---------- DocxRenderer/src/logic/elements/ContText.cpp | 30 ++++++++-------- DocxRenderer/src/logic/elements/ContText.h | 2 ++ DocxRenderer/src/logic/elements/Shape.h | 1 - DocxRenderer/src/logic/elements/TextLine.cpp | 38 +++++++++++++++++++- DocxRenderer/src/logic/elements/TextLine.h | 3 ++ 6 files changed, 75 insertions(+), 36 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 2aef825cdc..5de5b5ae13 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -1712,6 +1712,8 @@ namespace NSDocxRenderer // alignment check bool is_first_line = false; + Position curr_position = {true, true, true}; + for (size_t index = 0; index < ar_positions.size() - 1; ++index) { Position& position = ar_positions[index]; @@ -1720,9 +1722,17 @@ namespace NSDocxRenderer auto& line_bot = text_lines[index + 1]; if (index == 0 || ar_delims[index - 1]) + { is_first_line = true; + curr_position = position; + } else + { is_first_line = false; + curr_position.left &= position.left; + curr_position.center &= position.center; + curr_position.right &= position.right; + } // первая строка может быть с отступом if (is_first_line) @@ -1738,33 +1748,20 @@ namespace NSDocxRenderer else ar_indents[index] = true; } + if (ar_indents[index]) + curr_position.left = true; - bool is_unknown = !((position.left || ar_indents[index]) || position.right || position.center); - bool bullet_skip = false; + bool is_unknown = !(curr_position.left || curr_position.right || curr_position.center); + bool is_enum = false; if (is_unknown) { // bullet paragraphs if (!ar_delims[index]) { - const auto& first_sym = line_top->m_arConts.front()->GetText().at(0); - if (CContText::IsUnicodeBullet(first_sym)) - { - double left_no_first = 0; - bool out = false; - for (size_t i = 0; i < line_top->m_arConts.size() && !out; ++i) - for (size_t j = i ? 0 : 1; j < line_top->m_arConts[i]->GetLength() && !out; ++j) - if (!CContText::IsUnicodeSpace(line_top->m_arConts[i]->GetText().at(j))) - { - left_no_first = line_top->m_arConts[i]->GetSymLefts().at(j); - out = true; - break; - } - - if (out && fabs(left_no_first - line_bot->m_dLeft) < c_dERROR_OF_PARAGRAPH_BORDERS_MM) - bullet_skip = true; - } + double left_no_enum = line_top->GetLeftNoEnum(); + is_enum = left_no_enum != line_top->m_dLeft && fabs(left_no_enum - line_bot->m_dLeft) < c_dERROR_OF_PARAGRAPH_BORDERS_MM; } - if (!bullet_skip) + if (!is_enum) ar_delims[index] = true; } } diff --git a/DocxRenderer/src/logic/elements/ContText.cpp b/DocxRenderer/src/logic/elements/ContText.cpp index 1abb30be1e..566d934f49 100644 --- a/DocxRenderer/src/logic/elements/ContText.cpp +++ b/DocxRenderer/src/logic/elements/ContText.cpp @@ -6,18 +6,6 @@ namespace NSDocxRenderer { - bool IsTextOnlySpaces(const NSStringUtils::CStringUTF32& oText) - { - bool only_spaces = true; - for (size_t j = 0; j < oText.length(); ++j) - if (!CContText::IsUnicodeSpace(oText.at(j))) - { - only_spaces = false; - break; - } - return only_spaces; - } - CSelectedSizes::CSelectedSizes(const CSelectedSizes& oSelectedSizes) { *this = oSelectedSizes; @@ -549,7 +537,14 @@ namespace NSDocxRenderer bool CContText::IsOnlySpaces() const { - return IsTextOnlySpaces(m_oText); + bool only_spaces = true; + for (size_t j = 0; j < m_oText.length(); ++j) + if (!CContText::IsUnicodeSpace(m_oText.at(j))) + { + only_spaces = false; + break; + } + return only_spaces; } bool CContText::IsDiacritical() const noexcept { @@ -841,7 +836,14 @@ namespace NSDocxRenderer return is_bullet || is_another; } - + bool CContText::IsUnicodeEnumEnd(uint32_t cSym) + { + return cSym == 0x29 || cSym == 0x2e; + } + bool CContText::IsUnicodeNumber(uint32_t cSym) + { + return cSym >= 0x30 && cSym <= 0x39; + } bool CContText::IsUnicodeSpace(uint32_t cSym) { return (0x20 == cSym || 0xA0 == cSym || 0x2003 == cSym); diff --git a/DocxRenderer/src/logic/elements/ContText.h b/DocxRenderer/src/logic/elements/ContText.h index e0c582ce1f..e1de82704f 100644 --- a/DocxRenderer/src/logic/elements/ContText.h +++ b/DocxRenderer/src/logic/elements/ContText.h @@ -136,6 +136,8 @@ namespace NSDocxRenderer static bool IsUnicodeRtl(uint32_t cSym); static bool IsUnicodeBullet(uint32_t cSym); + static bool IsUnicodeEnumEnd(uint32_t cSym); + static bool IsUnicodeNumber(uint32_t cSym); static bool IsUnicodeSpace(uint32_t c); static bool IsUnicodeSymbol(uint32_t symbol); static bool IsUnicodeDiacriticalMark(uint32_t symbol); diff --git a/DocxRenderer/src/logic/elements/Shape.h b/DocxRenderer/src/logic/elements/Shape.h index 4a6b878672..0599b07b09 100644 --- a/DocxRenderer/src/logic/elements/Shape.h +++ b/DocxRenderer/src/logic/elements/Shape.h @@ -65,7 +65,6 @@ namespace NSDocxRenderer std::vector> m_arOutputObjects; - public: CShape(); CShape(std::shared_ptr pInfo, const std::wstring& strDstMedia); diff --git a/DocxRenderer/src/logic/elements/TextLine.cpp b/DocxRenderer/src/logic/elements/TextLine.cpp index 5af0ec5af6..2d1905c097 100644 --- a/DocxRenderer/src/logic/elements/TextLine.cpp +++ b/DocxRenderer/src/logic/elements/TextLine.cpp @@ -37,6 +37,25 @@ namespace NSDocxRenderer return true; } + double CTextLine::GetLeftNoEnum() const noexcept + { + double left_no_enum = m_dLeft; + const auto& first_sym = m_arConts.front()->GetText().at(0); + + size_t i = 0, j = 0; + GetNextSym(i, j); + + if (CContText::IsUnicodeBullet(first_sym)) + { + while (CContText::IsUnicodeSpace(m_arConts[i]->GetText().at(j)) && i && j) GetNextSym(i, j); + + // one more time to get next + GetNextSym(i, j); + left_no_enum = (!i && !j) ? m_arConts.back()->m_dRight : m_arConts[i]->GetSymLefts().at(j); + } + return left_no_enum; + } + void CTextLine::MergeConts() { if (m_arConts.empty()) @@ -203,7 +222,7 @@ namespace NSDocxRenderer m_dHeight = 0.0; for (const auto& cont : m_arConts) - if(cont) + if (cont) RecalcWithNewItem(cont.get()); } @@ -303,4 +322,21 @@ namespace NSDocxRenderer return len; } + void CTextLine::GetNextSym(size_t& nContPos, size_t& nSymPos) const noexcept + { + ++nSymPos; + if (m_arConts[nContPos]->GetLength() <= nSymPos) + for (nContPos = nContPos + 1; nContPos < m_arConts.size(); ++nContPos) + if (m_arConts[nContPos] && m_arConts[nContPos]->GetLength() != 0) + { + nSymPos = 0; + break; + } + + if (m_arConts.size() <= nContPos) + { + nContPos = 0; + nSymPos = 0; + } + } } diff --git a/DocxRenderer/src/logic/elements/TextLine.h b/DocxRenderer/src/logic/elements/TextLine.h index 9919337aed..05796a6e88 100644 --- a/DocxRenderer/src/logic/elements/TextLine.h +++ b/DocxRenderer/src/logic/elements/TextLine.h @@ -50,6 +50,9 @@ namespace NSDocxRenderer bool IsShadingPresent(const CTextLine* pLine) const noexcept; bool IsCanBeDeleted() const; + double GetLeftNoEnum() const noexcept; + size_t GetLength() const; + void GetNextSym(size_t& nContPos, size_t& nSymPos) const noexcept; }; } From 9991cc8c032558fe7833b7333c4e6b4e38a36eba Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Tue, 17 Dec 2024 15:13:53 +0300 Subject: [PATCH 10/17] Rewrite split lines logic --- DocxRenderer/src/logic/Page.cpp | 122 ++++++++---------- DocxRenderer/src/logic/Page.h | 7 +- DocxRenderer/src/resources/VectorGraphics.cpp | 8 +- DocxRenderer/src/resources/VectorGraphics.h | 15 ++- 4 files changed, 70 insertions(+), 82 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 5de5b5ae13..644cfea1f0 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -703,7 +703,20 @@ namespace NSDocxRenderer { for (const auto& shape : m_arShapes) if (shape) + { + const double out_of_page_coeff = 1.1; + bool is_out_of_page = shape->m_dTop < 0 || + shape->m_dBaselinePos > this->m_dHeight * out_of_page_coeff || + shape->m_dLeft < 0 || + shape->m_dRight > this->m_dWidth * out_of_page_coeff; + + bool is_too_big = (shape->m_dWidth > c_dSHAPE_TROUGH_MAX_MM || shape->m_dHeight > c_dSHAPE_TROUGH_MAX_MM); + + if (is_too_big || is_out_of_page) + continue; + m_oHorVerLinesCollector.AddVector(shape->m_oVector); + } } void CPage::AnalyzeTextLines() @@ -1240,89 +1253,59 @@ namespace NSDocxRenderer } } - bool CPage::IsShapeBorderBetweenVertical(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept + bool CPage::IsVerticalLineBetween(item_ptr_t pFirst, item_ptr_t pSecond) const noexcept { double left = std::min(pFirst->m_dRight, pSecond->m_dRight); double right = std::max(pFirst->m_dLeft, pSecond->m_dLeft); - double top = std::min(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); - double bot = std::max(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); + double top = std::min(pFirst->m_dTop, pSecond->m_dTop); + double bot = std::max(pFirst->m_dBaselinePos, pSecond->m_dBaselinePos); auto dummy_cont = std::make_shared(); - dummy_cont->m_dLeft = left; - dummy_cont->m_dRight = right; - dummy_cont->m_dTopWithAscent = top; - dummy_cont->m_dBotWithDescent = bot; + dummy_cont->m_dLeft = left - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dRight = right + c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dTop = top - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dBaselinePos = bot + c_dGRAPHICS_ERROR_MM; - double dx = 0, dy = 0; - bool is_shape_trough = IsShapeBorderTrough(dummy_cont, dx, dy); - if (is_shape_trough && dy * 2 > bot - top) return true; - return false; + return IsVerticalLineTrough(dummy_cont); } - - bool CPage::IsShapeBorderBetweenHorizontal(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept + bool CPage::IsHorizontalLineBetween(item_ptr_t pFirst, item_ptr_t pSecond) const noexcept { double left = std::min(pFirst->m_dLeft, pSecond->m_dLeft); double right = std::max(pFirst->m_dRight, pSecond->m_dRight); - double top = std::min(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); - double bot = std::max(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); + double top = std::min(pFirst->m_dBaselinePos, pSecond->m_dBaselinePos); + double bot = std::max(pFirst->m_dTop, pSecond->m_dTop); auto dummy_cont = std::make_shared(); - dummy_cont->m_dLeft = left; - dummy_cont->m_dRight = right; - dummy_cont->m_dTopWithAscent = top; - dummy_cont->m_dBotWithDescent = bot; + dummy_cont->m_dLeft = left - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dRight = right + c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dTop = top - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dBaselinePos = bot + c_dGRAPHICS_ERROR_MM; - double dx = 0, dy = 0; - bool is_shape_trough = IsShapeBorderTrough(dummy_cont, dx, dy); - if (is_shape_trough && dx * 2 > right - left) return true; - return false; + return IsHorizontalLineTrough(dummy_cont); } - bool CPage::IsShapeBorderTrough(cont_ptr_t pItem, double& dXCrossing, double& dYCrossing) const noexcept + bool CPage::IsVerticalLineTrough(item_ptr_t pFirst) const noexcept { - double left = pItem->m_dLeft; - double right = pItem->m_dRight; - double top = pItem->m_dTopWithAscent; - double bot = pItem->m_dBotWithDescent; + const auto& ver_lines = m_oHorVerLinesCollector.GetVertical(); + const auto height = pFirst->m_dBaselinePos - pFirst->m_dTop; + const auto center = pFirst->m_dTop + height / 2; - for (const auto& shape : m_arShapes) - { - if (!shape) - continue; - - const double out_of_page_coeff = 1.1; - bool is_out_of_page = shape->m_dTop < 0 || - shape->m_dBaselinePos > this->m_dHeight * out_of_page_coeff || - shape->m_dLeft < 0 || - shape->m_dRight > this->m_dWidth * out_of_page_coeff; - bool is_too_big = ((shape->m_dWidth > c_dSHAPE_TROUGH_MAX_MM || shape->m_dHeight > c_dSHAPE_TROUGH_MAX_MM) && - (shape->m_eSimpleLineType == eSimpleLineType::sltUnknown)); - - if (is_too_big || is_out_of_page) - continue; - - double& s_left = shape->m_dLeft; - double& s_right = shape->m_dRight; - double& s_top = shape->m_dTop; - double& s_bot = shape->m_dBaselinePos; - - bool lines_condition = shape->m_eSimpleLineType != eSimpleLineType::sltUnknown && - !((s_right < left) || (s_left > right)) && - !((s_bot < top) || (s_top > bot)); - - bool rectangle_condition = shape->m_eGraphicsType == eGraphicsType::gtRectangle && - shape->m_eSimpleLineType == eSimpleLineType::sltUnknown && - !((s_right < left) || (s_left > right)) && - !((s_bot < top) || (s_top > bot)) && - !(s_top < top && s_bot > bot && s_left < left && s_right > right); - - if (lines_condition || rectangle_condition) - { - dXCrossing = std::min(right, s_right) - std::max(left, s_left); - dYCrossing = std::min(bot, s_bot) - std::max(top, s_top); + for (const auto& line : ver_lines) + if (line.pos > pFirst->m_dLeft && line.pos < pFirst->m_dRight && line.min <= center && line.max >= center) return true; - } - } + + return false; + } + bool CPage::IsHorizontalLineTrough(item_ptr_t pFirst) const noexcept + { + const auto& hor_lines = m_oHorVerLinesCollector.GetHorizontal(); + const auto width = pFirst->m_dRight - pFirst->m_dLeft; + const auto center = pFirst->m_dLeft + width / 2; + + for (const auto& line : hor_lines) + if (line.pos > pFirst->m_dTop && line.pos < pFirst->m_dBaselinePos && line.min <= center && line.max >= center) + return true; + return false; } @@ -1340,10 +1323,7 @@ namespace NSDocxRenderer { bool is_space = line->m_arConts[i] && line->m_arConts[i]->GetText().ToStdWString() == L" "; bool is_cont_wide = line->m_arConts[i]->m_dWidth > c_dLINE_SPLIT_DISTANCE_MM; - - double x_crossing{}; - double y_crossing{}; - bool is_shape_trough = IsShapeBorderTrough(line->m_arConts[i], x_crossing, y_crossing); + bool is_shape_trough = IsVerticalLineTrough(line->m_arConts[i]); if ((i != line->m_arConts.size() - 1 && line->m_arConts[i + 1]->m_bPossibleSplit && is_space) || (is_space && is_cont_wide) @@ -1712,7 +1692,7 @@ namespace NSDocxRenderer // alignment check bool is_first_line = false; - Position curr_position = {true, true, true}; + Position curr_position; for (size_t index = 0; index < ar_positions.size() - 1; ++index) { @@ -1826,7 +1806,7 @@ namespace NSDocxRenderer // если между линий шейп - делим for (size_t index = 0; index < ar_positions.size() - 1; ++index) { - if (IsShapeBorderBetweenHorizontal(text_lines[index], text_lines[index + 1])) + if (IsHorizontalLineBetween(text_lines[index], text_lines[index + 1])) ar_delims[index] = true; } diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index 399560f95f..c0543214c9 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -162,9 +162,10 @@ namespace NSDocxRenderer bool IsHighlight(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept; bool IsOutline(shape_ptr_t pShape, cont_ptr_t pCont) const noexcept; - bool IsShapeBorderBetweenVertical(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; - bool IsShapeBorderBetweenHorizontal(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; - bool IsShapeBorderTrough(cont_ptr_t pItem, double& dXCrossing, double& dYCrossing) const noexcept; + bool IsVerticalLineBetween(item_ptr_t pFirst, item_ptr_t pSecond) const noexcept; + bool IsHorizontalLineBetween(item_ptr_t pFirst, item_ptr_t pSecond) const noexcept; + bool IsVerticalLineTrough(item_ptr_t pFirst) const noexcept; + bool IsHorizontalLineTrough(item_ptr_t pFirst) const noexcept; void ToXml(NSStringUtils::CStringBuilder& oWriter) const noexcept; void WriteSectionToFile(bool bLastPage, NSStringUtils::CStringBuilder& oWriter) const noexcept; diff --git a/DocxRenderer/src/resources/VectorGraphics.cpp b/DocxRenderer/src/resources/VectorGraphics.cpp index b87b082f22..8900715979 100644 --- a/DocxRenderer/src/resources/VectorGraphics.cpp +++ b/DocxRenderer/src/resources/VectorGraphics.cpp @@ -388,11 +388,11 @@ namespace NSDocxRenderer return points; } - const std::vector>& CHorVerLinesCollector::GetHorizontal() + const std::vector& CHorVerLinesCollector::GetHorizontal() const { return m_arHorizontal; } - const std::vector>& CHorVerLinesCollector::GetVertical() + const std::vector& CHorVerLinesCollector::GetVertical() const { return m_arVertical; } @@ -410,10 +410,10 @@ namespace NSDocxRenderer double y = command.points.front().y; if (x - last_x <= std::numeric_limits::epsilon()) - m_arVertical.push_back({last_y, y}); + m_arVertical.push_back({std::min(last_y, y), std::max(last_y, y), x}); else if (y - last_y <= std::numeric_limits::epsilon()) - m_arHorizontal.push_back({last_x, x}); + m_arHorizontal.push_back({std::min(last_x, x), std::max(last_x, x), y}); } if (!command.points.empty()) { diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index 6ec53346b1..825ce703fb 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -100,17 +100,24 @@ namespace NSDocxRenderer class CHorVerLinesCollector { public: + struct CHorVerLine + { + double min{}; + double max{}; + double pos{}; + }; + CHorVerLinesCollector() = default; ~CHorVerLinesCollector() = default; - const std::vector>& GetHorizontal(); - const std::vector>& GetVertical(); + const std::vector& GetHorizontal() const; + const std::vector& GetVertical() const; void AddVector(const CVectorGraphics& oVector); void Clear(); private: - std::vector> m_arHorizontal; - std::vector> m_arVertical; + std::vector m_arHorizontal; + std::vector m_arVertical; }; } From 48d86cb7ceacc1375067d0575156431e89250a5c Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Tue, 17 Dec 2024 15:39:50 +0300 Subject: [PATCH 11/17] Add base classes --- DocxRenderer/src/logic/elements/Table.cpp | 49 +++++++++++++++++++++++ DocxRenderer/src/logic/elements/Table.h | 24 +++++++++++ 2 files changed, 73 insertions(+) diff --git a/DocxRenderer/src/logic/elements/Table.cpp b/DocxRenderer/src/logic/elements/Table.cpp index 92ab704c98..4074fe87bd 100644 --- a/DocxRenderer/src/logic/elements/Table.cpp +++ b/DocxRenderer/src/logic/elements/Table.cpp @@ -2,5 +2,54 @@ namespace NSDocxRenderer { + void CTable::CCell::Clear() + { + + } + void CTable::CCell::ToXml(NSStringUtils::CStringBuilder& oWriter) const + { + + } + void CTable::CCell::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const + { + + } + + void CTable::CRow::Clear() + { + + } + void CTable::CRow::ToXml(NSStringUtils::CStringBuilder& oWriter) const + { + + } + void CTable::CRow::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const + { + + } + + void CTable::Clear() + { + + } + void CTable::ToXml(NSStringUtils::CStringBuilder& oWriter) const + { + oWriter.WriteString(L""); + + oWriter.WriteString(L""); + oWriter.WriteString(L""); + + oWriter.WriteString(L""); + oWriter.WriteString(L""); + + oWriter.WriteString(L""); + oWriter.WriteString(L""); + + oWriter.WriteString(L""); + } + void CTable::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const + { + + } } // namespace NSDocxRenderer diff --git a/DocxRenderer/src/logic/elements/Table.h b/DocxRenderer/src/logic/elements/Table.h index 8d711ee018..5a0f10cb89 100644 --- a/DocxRenderer/src/logic/elements/Table.h +++ b/DocxRenderer/src/logic/elements/Table.h @@ -6,8 +6,32 @@ namespace NSDocxRenderer { class CTable : public CBaseItem { + public: + class CRow : CBaseItem + { + public: + CRow() = default; + virtual ~CRow() = default; + virtual void Clear() override final; + virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; + virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; + }; + + class CCell : CBaseItem + { + public: + CCell() = default; + virtual ~CCell() = default; + virtual void Clear() override final; + virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; + virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; + }; + CTable() = default; virtual ~CTable() = default; + virtual void Clear() override final; + virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; + virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; }; } // namespace NSDocxRenderer From 02aeaa6a642d9d0bfd2798bf58639dcd8e9f587f Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Fri, 20 Dec 2024 17:38:56 +0300 Subject: [PATCH 12/17] Fix bug with ascent/descent --- DocxRenderer/src/logic/Page.cpp | 41 +++++++++++++++++++++++++++++---- DocxRenderer/src/logic/Page.h | 6 ++++- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 644cfea1f0..12db92a4dd 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -710,7 +710,8 @@ namespace NSDocxRenderer shape->m_dLeft < 0 || shape->m_dRight > this->m_dWidth * out_of_page_coeff; - bool is_too_big = (shape->m_dWidth > c_dSHAPE_TROUGH_MAX_MM || shape->m_dHeight > c_dSHAPE_TROUGH_MAX_MM); + + bool is_too_big = (!shape->m_bIsNoFill && (shape->m_dWidth > c_dSHAPE_TROUGH_MAX_MM || shape->m_dHeight > c_dSHAPE_TROUGH_MAX_MM)); if (is_too_big || is_out_of_page) continue; @@ -729,11 +730,13 @@ namespace NSDocxRenderer AnalyzeDropCaps(); AnalyzeConts(); AnalyzeEffects(); + + GetHorVerLines(); + AddDiacriticalSymbols(); - MergeLinesByVertAlignType(); + MergeTextLinesByVatType(); DeleteTextClipPage(); MergeConts(); - GetHorVerLines(); SplitLines(); AnalyzeOverlapLines(); @@ -1150,7 +1153,7 @@ namespace NSDocxRenderer } } - void CPage::MergeLinesByVertAlignType() + void CPage::MergeTextLinesByVatType() { for (auto& line : m_arTextLines) { @@ -1283,6 +1286,36 @@ namespace NSDocxRenderer return IsHorizontalLineTrough(dummy_cont); } + bool CPage::IsVerticalLineBetween(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept + { + double left = std::min(pFirst->m_dRight, pSecond->m_dRight); + double right = std::max(pFirst->m_dLeft, pSecond->m_dLeft); + double top = std::min(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); + double bot = std::max(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); + + auto dummy_cont = std::make_shared(); + dummy_cont->m_dLeft = left - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dRight = right + c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dTop = top - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dBaselinePos = bot + c_dGRAPHICS_ERROR_MM; + + return IsVerticalLineTrough(dummy_cont); + } + bool CPage::IsHorizontalLineBetween(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept + { + double left = std::min(pFirst->m_dLeft, pSecond->m_dLeft); + double right = std::max(pFirst->m_dRight, pSecond->m_dRight); + double top = std::min(pFirst->m_dBotWithMaxDescent, pSecond->m_dBotWithMaxDescent); + double bot = std::max(pFirst->m_dTopWithMaxAscent, pSecond->m_dTopWithMaxAscent); + + auto dummy_cont = std::make_shared(); + dummy_cont->m_dLeft = left - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dRight = right + c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dTop = top - c_dGRAPHICS_ERROR_MM; + dummy_cont->m_dBaselinePos = bot + c_dGRAPHICS_ERROR_MM; + + return IsHorizontalLineTrough(dummy_cont); + } bool CPage::IsVerticalLineTrough(item_ptr_t pFirst) const noexcept { diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index c0543214c9..d1b7a6407c 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -122,7 +122,7 @@ namespace NSDocxRenderer void AddDiacriticalSymbols(); // super-sub scripts line merge - void MergeLinesByVertAlignType(); + void MergeTextLinesByVatType(); // remove out of bounds text lines void DeleteTextClipPage(); @@ -164,6 +164,10 @@ namespace NSDocxRenderer bool IsVerticalLineBetween(item_ptr_t pFirst, item_ptr_t pSecond) const noexcept; bool IsHorizontalLineBetween(item_ptr_t pFirst, item_ptr_t pSecond) const noexcept; + + bool IsVerticalLineBetween(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; + bool IsHorizontalLineBetween(line_ptr_t pFirst, line_ptr_t pSecond) const noexcept; + bool IsVerticalLineTrough(item_ptr_t pFirst) const noexcept; bool IsHorizontalLineTrough(item_ptr_t pFirst) const noexcept; From 5f2d7b2f5af9f71dedce26016a8fe5ff95568f4a Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Fri, 20 Dec 2024 19:27:23 +0300 Subject: [PATCH 13/17] Add base xml for tables --- .../graphics/pro/js/drawingfile.json | 2 +- DocxRenderer/src/logic/Page.cpp | 13 +++- DocxRenderer/src/logic/Page.h | 6 ++ DocxRenderer/src/logic/elements/Table.cpp | 74 +++++++++++++++++-- DocxRenderer/src/logic/elements/Table.h | 62 +++++++++++++--- 5 files changed, 139 insertions(+), 18 deletions(-) diff --git a/DesktopEditor/graphics/pro/js/drawingfile.json b/DesktopEditor/graphics/pro/js/drawingfile.json index ffc62eada6..681f8f2b6b 100644 --- a/DesktopEditor/graphics/pro/js/drawingfile.json +++ b/DesktopEditor/graphics/pro/js/drawingfile.json @@ -223,7 +223,7 @@ }, { "folder": "../../../../DocxRenderer/src/logic/elements", - "files": ["BaseItem.cpp", "ContText.cpp", "Paragraph.cpp", "Shape.cpp", "TextLine.cpp"] + "files": ["BaseItem.cpp", "ContText.cpp", "Paragraph.cpp", "Shape.cpp", "TextLine.cpp", "Table.cpp"] }, { "folder": "../../../common", diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 12db92a4dd..81573e6eee 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -393,13 +393,13 @@ namespace NSDocxRenderer m_arDiacriticalSymbols = MoveDiacriticalSymbols(); m_arTextLines = BuildTextLines(); - // analyzing data + // analyzing data. can take shapes and set them to nullptr AnalyzeShapes(); AnalyzeTextLines(); // building final objects m_arParagraphs = BuildParagraphs(); - // TODO: tables + // m_arTables = BuildTables(); // post analyze CalcSelected(); @@ -1877,6 +1877,15 @@ namespace NSDocxRenderer return ar_paragraphs; } + std::vector CPage::BuildTables() + { + // build cells + // add paragraphs + // build rows + // build tables + std::vector ar_tables; + return ar_tables; + } CPage::shape_ptr_t CPage::CreateSingleLineShape(line_ptr_t& pLine) { diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index d1b7a6407c..af8948fdd3 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -1,6 +1,7 @@ #pragma once #include "elements/Paragraph.h" +#include "elements/Table.h" #include "elements/Shape.h" #include "managers/ImageManager.h" #include "managers/FontStyleManager.h" @@ -87,6 +88,7 @@ namespace NSDocxRenderer using line_ptr_t = std::shared_ptr; using item_ptr_t = std::shared_ptr; using paragraph_ptr_t = std::shared_ptr; + using table_ptr_t = std::shared_ptr; // returns std::vector of conts with diac. symbols and remove it from m_arConts std::vector MoveDiacriticalSymbols(); @@ -97,6 +99,9 @@ namespace NSDocxRenderer // returns std::vector of paragraphs builded from m_arTextLines std::vector BuildParagraphs(); + // returns std::vector of tables builded from shapes and paragraphes + std::vector BuildTables(); + // returns std::vector of base items builded from m_arParagraphs std::vector BuildOutputObjects(); @@ -190,6 +195,7 @@ namespace NSDocxRenderer std::vector m_arDiacriticalSymbols; std::vector m_arShapes; std::vector m_arParagraphs; + std::vector m_arTables; std::vector m_arOutputObjects; std::vector m_arCompleteObjectsXml; diff --git a/DocxRenderer/src/logic/elements/Table.cpp b/DocxRenderer/src/logic/elements/Table.cpp index 4074fe87bd..4c0042a562 100644 --- a/DocxRenderer/src/logic/elements/Table.cpp +++ b/DocxRenderer/src/logic/elements/Table.cpp @@ -1,49 +1,108 @@ #include "Table.h" +#include "../../resources/SingletonTemplate.h" +#include "../../resources/utils.h" + namespace NSDocxRenderer { void CTable::CCell::Clear() { - + m_arParagraphs.clear(); } void CTable::CCell::ToXml(NSStringUtils::CStringBuilder& oWriter) const { + oWriter.WriteString(L""); + oWriter.WriteString(L""); + oWriter.WriteString(L"(m_dWidth * c_dMMToDx)); + oWriter.WriteString(L"\"w:type=\"dxa\"/>"); + oWriter.WriteString(L""); + + auto write_border = [&oWriter] (const CBorder& border, const std::wstring& prefix) { + oWriter.WriteString(L"().ConvertLineToString(border.eLineType)); + oWriter.WriteString(L"\" w:sz=\""); + oWriter.AddUInt(static_cast(border.dWidth * c_dMMToPt / 8)); + oWriter.WriteString(L"\" w:space=\""); + oWriter.AddUInt(static_cast(border.dSpacing * c_dMMToPt)); + oWriter.WriteString(L"\" w:color=\""); + oWriter.WriteHexInt3(ConvertColorBGRToRGB(border.lColor)); + oWriter.WriteString(L"\">"); + }; + + write_border(m_oBorderTop, L"top"); + write_border(m_oBorderBot, L"bot"); + write_border(m_oBorderLeft, L"left"); + write_border(m_oBorderRight, L"right"); + + oWriter.WriteString(L"/"); + oWriter.WriteString(L"/"); + + for (const auto& p : m_arParagraphs) + p->ToXml(oWriter); + + oWriter.WriteString(L"/"); } void CTable::CCell::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const { } + void CTable::CCell::AddParagraph(const paragraph_ptr_t& pParagraph) + { + m_arParagraphs.push_back(pParagraph); + } void CTable::CRow::Clear() { - + m_arCells.clear(); } void CTable::CRow::ToXml(NSStringUtils::CStringBuilder& oWriter) const { + oWriter.WriteString(L""); + oWriter.WriteString(L""); + oWriter.WriteString(L"(m_dHeight * c_dMMToDx)); + oWriter.WriteString(L"\" w:hRule=\"exact\"/>"); + oWriter.WriteString(L""); + + for (const auto& c : m_arCells) + c->ToXml(oWriter); + + oWriter.WriteString(L"/"); } void CTable::CRow::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const { } + void CTable::CRow::AddCell(const cell_ptr_t& pCell) + { + CBaseItem::RecalcWithNewItem(pCell.get()); + m_arCells.push_back(pCell); + } void CTable::Clear() { - + m_arRows.clear(); } void CTable::ToXml(NSStringUtils::CStringBuilder& oWriter) const { oWriter.WriteString(L""); oWriter.WriteString(L""); + oWriter.WriteString(L"(m_dWidth * c_dMMToDx)); + oWriter.WriteString(L"\"w:type=\"dxa\"/>"); oWriter.WriteString(L""); oWriter.WriteString(L""); oWriter.WriteString(L""); - oWriter.WriteString(L""); - oWriter.WriteString(L""); + for (const auto& r : m_arRows) + r->ToXml(oWriter); oWriter.WriteString(L""); } @@ -51,5 +110,10 @@ namespace NSDocxRenderer { } + void CTable::AddRow(const row_ptr_t& pRow) + { + CBaseItem::RecalcWithNewItem(pRow.get()); + m_arRows.push_back(pRow); + } } // namespace NSDocxRenderer diff --git a/DocxRenderer/src/logic/elements/Table.h b/DocxRenderer/src/logic/elements/Table.h index 5a0f10cb89..ad55b2fb49 100644 --- a/DocxRenderer/src/logic/elements/Table.h +++ b/DocxRenderer/src/logic/elements/Table.h @@ -1,13 +1,55 @@ #pragma once +#include +#include + #include "BaseItem.h" +#include "Paragraph.h" + +#include "../../resources/LinesTable.h" namespace NSDocxRenderer { class CTable : public CBaseItem { public: - class CRow : CBaseItem + class CCell; + class CRow; + + private: + using cell_ptr_t = std::shared_ptr; + using row_ptr_t = std::shared_ptr; + using paragraph_ptr_t = std::shared_ptr; + + public: + class CCell : public CBaseItem + { + public: + struct CBorder + { + double dWidth{}; + double dSpacing{}; + long lColor{}; + eLineType eLineType{}; + }; + + CCell() = default; + virtual ~CCell() = default; + virtual void Clear() override final; + virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; + virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; + + void AddParagraph(const paragraph_ptr_t& pParagraph); + + CBorder m_oBorderTop; + CBorder m_oBorderBot; + CBorder m_oBorderLeft; + CBorder m_oBorderRight; + + private: + std::vector m_arParagraphs; + }; + class CRow : public CBaseItem { public: CRow() = default; @@ -15,16 +57,11 @@ namespace NSDocxRenderer virtual void Clear() override final; virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; - }; - class CCell : CBaseItem - { - public: - CCell() = default; - virtual ~CCell() = default; - virtual void Clear() override final; - virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; - virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; + void AddCell(const cell_ptr_t& pCell); + + private: + std::vector m_arCells; }; CTable() = default; @@ -32,6 +69,11 @@ namespace NSDocxRenderer virtual void Clear() override final; virtual void ToXml(NSStringUtils::CStringBuilder& oWriter) const override final; virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; + + void AddRow(const row_ptr_t& pRow); + + private: + std::vector m_arRows; }; } // namespace NSDocxRenderer From 6c79ab37fa283724a12fa2a02bf6704d4a60ad58 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Mon, 13 Jan 2025 17:16:52 +0300 Subject: [PATCH 14/17] Fix bug 72193 --- DocxRenderer/src/logic/Page.cpp | 3 ++- .../src/logic/managers/FontManager.cpp | 26 ++++++++++++------- DocxRenderer/src/logic/managers/FontManager.h | 4 +-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 81573e6eee..3edf02d0ed 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -350,7 +350,8 @@ namespace NSDocxRenderer m_oFont.Size *= ((m_oTransform.sx() + m_oTransform.sy()) / 2); m_bIsRecalcFontSize = false; } - m_oManagers.pFontManager->LoadFontByFile(m_oFont); + if (!m_oManagers.pFontManager->LoadFontByFile(m_oFont)) + return; double _x = 0; double _y = 0; diff --git a/DocxRenderer/src/logic/managers/FontManager.cpp b/DocxRenderer/src/logic/managers/FontManager.cpp index e3566e11e4..f2a6c6b591 100644 --- a/DocxRenderer/src/logic/managers/FontManager.cpp +++ b/DocxRenderer/src/logic/managers/FontManager.cpp @@ -530,13 +530,15 @@ namespace NSDocxRenderer RELEASEINTERFACE(m_pManager); } - void CFontManager::LoadFontByFile(const NSStructures::CFont& oFont) + bool CFontManager::LoadFontByFile(const NSStructures::CFont& oFont) { - if(m_oFont.IsEqual2(&oFont)) - return; + if (m_oFont.IsEqual2(&oFont)) + return true; + + if (!m_pManager->LoadFontFromFile(oFont.Path, (int)oFont.FaceIndex, (float)oFont.Size, c_dDpiX, c_dDpiY)) + return false; m_oFont = oFont; - m_pManager->LoadFontFromFile(m_oFont.Path, (int)m_oFont.FaceIndex, (float)m_oFont.Size, c_dDpiX, c_dDpiY); m_pManager->AfterLoad(); LoadFontMetrics(); @@ -546,18 +548,24 @@ namespace NSDocxRenderer m_oFontSelectParams.wsDefaultName = m_oFont.Name; CheckPdfResources(); + + return true; } - void CFontManager::LoadFontByName(const NSStructures::CFont& oFont) + bool CFontManager::LoadFontByName(const NSStructures::CFont& oFont) { - if(m_oFont.IsEqual2(&oFont)) - return; + if (m_oFont.IsEqual2(&oFont)) + return true; m_oFont = oFont; - m_pManager->LoadFontByName(m_oFont.Name, (float)m_oFont.Size, m_oFont.GetStyle2(), c_dDpiX, c_dDpiY); - m_pManager->AfterLoad(); + if (!m_pManager->LoadFontByName(m_oFont.Name, (float)m_oFont.Size, m_oFont.GetStyle2(), c_dDpiX, c_dDpiY)) + return false; + + m_pManager->AfterLoad(); LoadFontMetrics(); LoadFontSelectParams(); + + return true; } const CFontSelectParams& CFontManager::GetFontSelectParams() const noexcept diff --git a/DocxRenderer/src/logic/managers/FontManager.h b/DocxRenderer/src/logic/managers/FontManager.h index 7bb933c35e..17e4d7286a 100644 --- a/DocxRenderer/src/logic/managers/FontManager.h +++ b/DocxRenderer/src/logic/managers/FontManager.h @@ -117,8 +117,8 @@ namespace NSDocxRenderer CFontManager(NSFonts::IApplicationFonts* pFonts); ~CFontManager(); - void LoadFontByFile(const NSStructures::CFont& oFont); - void LoadFontByName(const NSStructures::CFont& oFont); + bool LoadFontByFile(const NSStructures::CFont& oFont); + bool LoadFontByName(const NSStructures::CFont& oFont); const CFontSelectParams& GetFontSelectParams() const noexcept; const CFontMetrics& GetFontMetrics() const noexcept; From fdac954df521e8cfd74898c30c2fc683ee8f7574 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Mon, 20 Jan 2025 16:14:28 +0300 Subject: [PATCH 15/17] Add main logic of tables (in developing) --- DocxRenderer/src/logic/Page.cpp | 185 +++++++++++++++++++- DocxRenderer/src/logic/Page.h | 7 + DocxRenderer/src/logic/elements/Table.cpp | 22 ++- DocxRenderer/src/logic/elements/Table.h | 3 +- DocxRenderer/src/resources/VectorGraphics.h | 3 +- 5 files changed, 204 insertions(+), 16 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index 3edf02d0ed..ea3529573b 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -1,6 +1,7 @@ #include "Page.h" #include +#include #include "../../../DesktopEditor/graphics/GraphicsPath.h" #include "../../../DesktopEditor/graphics/pro/Graphics.h" @@ -400,7 +401,9 @@ namespace NSDocxRenderer // building final objects m_arParagraphs = BuildParagraphs(); - // m_arTables = BuildTables(); + + if (m_bIsBuildTables) + m_arTables = BuildTables(); // post analyze CalcSelected(); @@ -408,6 +411,8 @@ namespace NSDocxRenderer CalcShapesRotation(); m_arOutputObjects = BuildOutputObjects(); + for (auto& t : m_arTables) + m_arOutputObjects.push_back(t); } void CPage::Record(NSStringUtils::CStringBuilder& oWriter, bool bIsLastPage) @@ -1878,14 +1883,180 @@ namespace NSDocxRenderer return ar_paragraphs; } + std::vector CPage::BuildTables() { - // build cells - // add paragraphs - // build rows - // build tables - std::vector ar_tables; - return ar_tables; + auto cells = BuildCells(); + auto rows = BuildRows(cells); + std::vector tables; + + table_ptr_t curr_table = nullptr; + for (const auto& row : rows) + { + if (!curr_table) + { + curr_table = std::make_shared(); + } + else if (fabs(curr_table->m_dBaselinePos - row->m_dTop) > c_dGRAPHICS_ERROR_MM) + { + tables.push_back(std::move(curr_table)); + curr_table = std::make_shared(); + } + curr_table->AddRow(row); + } + if (!curr_table->IsEmpty()) + tables.push_back(std::move(curr_table)); + + return tables; + } + std::vector CPage::BuildCells() + { + struct Crossing + { + Point p {}; + std::vector lines {}; + }; + std::vector crossings; + auto find_crossing = [&crossings] (const Point& p) -> Crossing* { + for (auto& crossing : crossings) + { + if (fabs(crossing.p.x - p.x) < c_dGRAPHICS_ERROR_MM && + fabs(crossing.p.y - p.y) < c_dGRAPHICS_ERROR_MM) + return &crossing; + } + return nullptr; + }; + + for (const auto& shape : m_arShapes) + { + if (!shape) + continue; + + Point prev {}; + for (const auto& command : shape->m_oVector.GetData()) + { + if (!command.points.empty()) + { + if (command.type == CVectorGraphics::ePathCommandType::pctLine) + { + const auto& curr = command.points.back(); + auto prev_crossing = find_crossing(prev); + auto curr_crossing = find_crossing(curr); + + // add empty vector if no exists + if (!prev_crossing) + crossings.push_back({prev, {curr}}); + else + prev_crossing->lines.push_back(curr); + + if (!curr_crossing) + crossings.push_back({curr, {prev}}); + else + curr_crossing->lines.push_back(prev); + + prev = curr; + } + prev = command.points.back(); + } + } + } + + // sorting guarantee creating cell once (by taking second cross j > i) + std::sort(crossings.begin(), crossings.end(), [] (const Crossing& c1, const Crossing& c2) { + if (fabs(c1.p.y - c2.p.y) < c_dGRAPHICS_ERROR_MM) + return c1.p.x < c2.p.x; + return c1.p.y < c2.p.y; + }); + + std::vector cells; + for (size_t i = 0; i < crossings.size(); ++i) + { + for (size_t j = i + 1; j < crossings.size(); ++j) + { + const auto& first = crossings.at(i); + const auto& second = crossings.at(j); + + // first should be top left corner + // and second right bot (not the same line ofc) + if (fabs(first.p.x - second.p.x) < c_dGRAPHICS_ERROR_MM || + first.p.x > second.p.x || + fabs(first.p.y - second.p.y) < c_dGRAPHICS_ERROR_MM || + first.p.y > second.p.y) + continue; + + // 2 points should be the same + size_t equals = 0; + for (const auto& fl : first.lines) + for (const auto& sl : second.lines) + if (fabs(fl.x - sl.x) < c_dGRAPHICS_ERROR_MM && fabs(fl.y - sl.y) < c_dGRAPHICS_ERROR_MM) + ++equals; + + if (equals == 2) + { + auto cell = std::make_shared(); + cell->m_dLeft = first.p.x; + cell->m_dRight = second.p.x; + cell->m_dTop = first.p.y; + cell->m_dBaselinePos = second.p.y; + cell->m_dWidth = cell->m_dRight - cell->m_dLeft; + cell->m_dHeight = cell->m_dBaselinePos - cell->m_dTop; + cells.push_back(cell); + break; + } + } + } + + // sets paragraphs into cells + for (auto& cell : cells) + for (auto& paragraph : m_arParagraphs) + { + if (!paragraph) + continue; + + bool top = fabs(cell->m_dTop - paragraph->m_dTop) < 2 * c_dGRAPHICS_ERROR_MM || paragraph->m_dTop > cell->m_dTop; + bool bot = fabs(cell->m_dBaselinePos - paragraph->m_dBaselinePos) < c_dGRAPHICS_ERROR_MM || paragraph->m_dBaselinePos < cell->m_dBaselinePos; + bool left = fabs(cell->m_dLeft - paragraph->m_dLeft) < c_dGRAPHICS_ERROR_MM || paragraph->m_dLeft > cell->m_dLeft; + bool right = fabs(cell->m_dRight - paragraph->m_dRight) < c_dGRAPHICS_ERROR_MM || paragraph->m_dRight < cell->m_dRight; + if (top && bot && left && right) + { + cell->AddParagraph(paragraph); + paragraph = nullptr; + } + } + auto right = MoveNullptr(m_arParagraphs.begin(), m_arParagraphs.end()); + m_arParagraphs.erase(right, m_arParagraphs.end()); + std::sort(m_arParagraphs.begin(), m_arParagraphs.end(), [] (const paragraph_ptr_t& p1, const paragraph_ptr_t& p2) { + return p1->m_dBaselinePos < p2->m_dBaselinePos; + }); + return cells; + } + std::vector CPage::BuildRows(std::vector& arCells) + { + std::sort(arCells.begin(), arCells.end(), [] (const CTable::cell_ptr_t c1, const CTable::cell_ptr_t& c2) { + if (fabs(c1->m_dBaselinePos - c2->m_dBaselinePos) < c_dGRAPHICS_ERROR_MM) + return c1->m_dLeft < c2->m_dLeft; + return c1->m_dBaselinePos < c2->m_dBaselinePos; + }); + + std::vector rows; + CTable::row_ptr_t curr_row = nullptr; + for (auto& cell : arCells) + { + if (!curr_row) + { + curr_row = std::make_shared(); + } + else if (fabs(curr_row->m_dBaselinePos - cell->m_dBaselinePos) > c_dGRAPHICS_ERROR_MM) + { + rows.push_back(std::move(curr_row)); + curr_row = std::make_shared(); + } + curr_row->AddCell(cell); + } + if (!curr_row->IsEmpty()) + rows.push_back(std::move(curr_row)); + + return rows; } CPage::shape_ptr_t CPage::CreateSingleLineShape(line_ptr_t& pLine) diff --git a/DocxRenderer/src/logic/Page.h b/DocxRenderer/src/logic/Page.h index af8948fdd3..e17e9fcb19 100644 --- a/DocxRenderer/src/logic/Page.h +++ b/DocxRenderer/src/logic/Page.h @@ -46,6 +46,7 @@ namespace NSDocxRenderer bool m_bIsGradient {false}; bool m_bUseDefaultFont {false}; bool m_bWriteStyleRaw {false}; + bool m_bIsBuildTables {false}; CPage(NSFonts::IApplicationFonts* pAppFonts, const CManagers& oManagers); ~CPage(); @@ -102,6 +103,12 @@ namespace NSDocxRenderer // returns std::vector of tables builded from shapes and paragraphes std::vector BuildTables(); + // returns std::vector of cells for tables + std::vector BuildCells(); + + // returns std::vector of rows for tables + std::vector BuildRows(std::vector& arCells); + // returns std::vector of base items builded from m_arParagraphs std::vector BuildOutputObjects(); diff --git a/DocxRenderer/src/logic/elements/Table.cpp b/DocxRenderer/src/logic/elements/Table.cpp index 4c0042a562..b660ad166f 100644 --- a/DocxRenderer/src/logic/elements/Table.cpp +++ b/DocxRenderer/src/logic/elements/Table.cpp @@ -22,15 +22,15 @@ namespace NSDocxRenderer auto write_border = [&oWriter] (const CBorder& border, const std::wstring& prefix) { oWriter.WriteString(L"(border.dWidth * c_dMMToPt / 8)); oWriter.WriteString(L"\" w:space=\""); oWriter.AddUInt(static_cast(border.dSpacing * c_dMMToPt)); oWriter.WriteString(L"\" w:color=\""); oWriter.WriteHexInt3(ConvertColorBGRToRGB(border.lColor)); - oWriter.WriteString(L"\">"); + oWriter.WriteString(L"\" />"); }; write_border(m_oBorderTop, L"top"); @@ -38,13 +38,13 @@ namespace NSDocxRenderer write_border(m_oBorderLeft, L"left"); write_border(m_oBorderRight, L"right"); - oWriter.WriteString(L"/"); - oWriter.WriteString(L"/"); + oWriter.WriteString(L""); + oWriter.WriteString(L""); for (const auto& p : m_arParagraphs) p->ToXml(oWriter); - oWriter.WriteString(L"/"); + oWriter.WriteString(L""); } void CTable::CCell::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const { @@ -72,7 +72,7 @@ namespace NSDocxRenderer for (const auto& c : m_arCells) c->ToXml(oWriter); - oWriter.WriteString(L"/"); + oWriter.WriteString(L""); } void CTable::CRow::ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const { @@ -83,6 +83,10 @@ namespace NSDocxRenderer CBaseItem::RecalcWithNewItem(pCell.get()); m_arCells.push_back(pCell); } + bool CTable::CRow::IsEmpty() const + { + return m_arCells.empty(); + } void CTable::Clear() { @@ -115,5 +119,9 @@ namespace NSDocxRenderer CBaseItem::RecalcWithNewItem(pRow.get()); m_arRows.push_back(pRow); } + bool CTable::IsEmpty() const + { + return m_arRows.empty(); + } } // namespace NSDocxRenderer diff --git a/DocxRenderer/src/logic/elements/Table.h b/DocxRenderer/src/logic/elements/Table.h index ad55b2fb49..afeaf433f6 100644 --- a/DocxRenderer/src/logic/elements/Table.h +++ b/DocxRenderer/src/logic/elements/Table.h @@ -16,7 +16,6 @@ namespace NSDocxRenderer class CCell; class CRow; - private: using cell_ptr_t = std::shared_ptr; using row_ptr_t = std::shared_ptr; using paragraph_ptr_t = std::shared_ptr; @@ -59,6 +58,7 @@ namespace NSDocxRenderer virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; void AddCell(const cell_ptr_t& pCell); + bool IsEmpty() const; private: std::vector m_arCells; @@ -71,6 +71,7 @@ namespace NSDocxRenderer virtual void ToXmlPptx(NSStringUtils::CStringBuilder& oWriter) const override final; void AddRow(const row_ptr_t& pRow); + bool IsEmpty() const; private: std::vector m_arRows; diff --git a/DocxRenderer/src/resources/VectorGraphics.h b/DocxRenderer/src/resources/VectorGraphics.h index 825ce703fb..e18c638632 100644 --- a/DocxRenderer/src/resources/VectorGraphics.h +++ b/DocxRenderer/src/resources/VectorGraphics.h @@ -14,7 +14,8 @@ namespace NSDocxRenderer Point() {} Point(double x, double y) : x(x), y(y) {} Point(const Point& point) : x(point.x), y(point.y) {} - }; + Point& operator=(const Point& point) {x = point.x; y = point.y; return *this;} + };; class CVectorGraphics { From 3953044063423be0f0ab1edc887144040137c360 Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Wed, 22 Jan 2025 11:36:13 +0300 Subject: [PATCH 16/17] Add clearing --- DocxRenderer/src/logic/Page.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index ea3529573b..dc8ccc8487 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -60,6 +60,8 @@ namespace NSDocxRenderer m_arTextLines.clear(); m_arDiacriticalSymbols.clear(); m_arShapes.clear(); + m_arParagraphs.clear(); + m_arTables.clear(); m_arOutputObjects.clear(); m_oCurrVectorGraphics.Clear(); m_oClipVectorGraphics.Clear(); From 731a7addeea37535e55907fdee79542eb73c3aec Mon Sep 17 00:00:00 2001 From: Alexey Nagaev Date: Wed, 22 Jan 2025 12:57:21 +0300 Subject: [PATCH 17/17] Comment logic --- DocxRenderer/src/logic/Page.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index dc8ccc8487..9a2abbe76f 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -404,8 +404,8 @@ namespace NSDocxRenderer // building final objects m_arParagraphs = BuildParagraphs(); - if (m_bIsBuildTables) - m_arTables = BuildTables(); + // if (m_bIsBuildTables) + // m_arTables = BuildTables(); // post analyze CalcSelected(); @@ -413,8 +413,8 @@ namespace NSDocxRenderer CalcShapesRotation(); m_arOutputObjects = BuildOutputObjects(); - for (auto& t : m_arTables) - m_arOutputObjects.push_back(t); + // for (auto& t : m_arTables) + // m_arOutputObjects.push_back(t); } void CPage::Record(NSStringUtils::CStringBuilder& oWriter, bool bIsLastPage)