From 3e5c00571482e3727759fb3532f1771524a4ecfb Mon Sep 17 00:00:00 2001 From: SEAlGo Date: Wed, 1 Jun 2022 12:28:10 +0300 Subject: [PATCH] Fixed an problem with measuring a line with a long space. --- DocxRenderer/src/logic/ElementParagraph.cpp | 7 +++-- DocxRenderer/src/logic/ElementParagraph.h | 3 +- DocxRenderer/src/logic/Page.cpp | 31 ++++++++++++--------- DocxRenderer/test/main.cpp | 5 ++-- 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/DocxRenderer/src/logic/ElementParagraph.cpp b/DocxRenderer/src/logic/ElementParagraph.cpp index 9f03c02212..cd99052618 100644 --- a/DocxRenderer/src/logic/ElementParagraph.cpp +++ b/DocxRenderer/src/logic/ElementParagraph.cpp @@ -420,10 +420,13 @@ namespace NSDocxRenderer void CTextLine::CalculateWidth() { m_dWidth = 1; //todo исправить этот хак - по идее должно == 0. - for (size_t i = 0; i < m_arConts.size(); ++i) + + m_dWidth += m_arConts[0]->m_dWidthWithoutSpaces; + + for (size_t i = 1; i < m_arConts.size(); ++i) { + m_dWidth += m_arConts[i]->m_dLeftWithoutSpaces - (m_arConts[i-1]->m_dLeftWithoutSpaces + m_arConts[i-1]->m_dWidthWithoutSpaces);; m_dWidth += m_arConts[i]->m_dWidthWithoutSpaces; - m_dWidth += m_arConts[i]->m_dSpaceWidthMM; //заранее добавляем ширину пробелов } } diff --git a/DocxRenderer/src/logic/ElementParagraph.h b/DocxRenderer/src/logic/ElementParagraph.h index e3d00501a4..900669f5d7 100644 --- a/DocxRenderer/src/logic/ElementParagraph.h +++ b/DocxRenderer/src/logic/ElementParagraph.h @@ -9,7 +9,8 @@ namespace NSDocxRenderer const double c_dMMToDx = 72 * 20 / 25.4; const double c_dSTANDART_STRING_HEIGHT_MM = 4.2333333333333334; const double c_dTHE_SAME_STRING_Y_PRECISION_MM = 0.01; - const double c_dTHE_STRING_X_PRECISION_MM = 0.5; + const double c_dLINE_DISTANCE_ERROR_MM = 1.5; + const double c_dTHE_STRING_X_PRECISION_MM = 1.5; // у класса T должен быть метод IsBigger, IsBiggerOrEqual template diff --git a/DocxRenderer/src/logic/Page.cpp b/DocxRenderer/src/logic/Page.cpp index e3f0ecdb1a..a2c5ad2175 100644 --- a/DocxRenderer/src/logic/Page.cpp +++ b/DocxRenderer/src/logic/Page.cpp @@ -825,12 +825,13 @@ namespace NSDocxRenderer void CPage::BuildByTypePlainParagraph() { - //todo если линия содержит длинный пробел, то выравнивание по правому краю неправильно - //(больше чем нужно относительно правого края) Поэтому строка переносится + //todo выравнивание по высоте имеет погрешности - есть небольшое смещение //todo не отображается перенос в линии //todo если в линии есть перенос нужно обеъдинить строки в один параграф + //todo сноски не работают - формат сохраняется на всю строку + //todo добавить различные типы текста для распознавания: обычный-сплошной, списки-содержание и тд SortElements(m_arTextLine); @@ -857,6 +858,10 @@ namespace NSDocxRenderer pNextLine = nullptr : pNextLine = m_arTextLine[nNextIndex]; + nIndex == 0 ? + pPrevLine = nullptr : + pPrevLine = m_arTextLine[nIndex-1]; + dCurrRight = m_dWidth - (pCurrLine->m_dX + pCurrLine->m_dWidth + pCurrLine->m_arConts.back()->m_dSpaceWidthMM); //добавляем ширину пробела if (pNextLine) dNextRight = m_dWidth - (pNextLine->m_dX + pNextLine->m_dWidth + pNextLine->m_arConts.back()->m_dSpaceWidthMM); @@ -865,7 +870,6 @@ namespace NSDocxRenderer dCurrBeforeSpacing = pCurrLine->m_dBaselinePos - dPreviousStringOffset - pCurrLine->m_dHeight - pCurrLine->m_dBaselineOffset; dPreviousStringOffset = pCurrLine->m_dBaselinePos - pCurrLine->m_dBaselineOffset; - /*if (pNextLine && fabs(pCurrLine->m_dBaselinePos - pNextLine->m_dBaselinePos - pNextLine->m_dHeight) < c_dSTANDART_STRING_HEIGHT_MM && //fabs(pCurrLine->m_dBaselinePos - pNextLine->m_dBaselinePos) < c_dTHE_SAME_STRING_Y_PRECISION_MM && //если примерно на одной строке @@ -914,15 +918,19 @@ namespace NSDocxRenderer pParagraph->m_dLeft = std::min(pCurrLine->m_dX, pNextLine->m_dX); pParagraph->m_dWidth = std::max(pCurrLine->m_dWidth + pCurrLine->m_arConts.back()->m_dSpaceWidthMM, pNextLine->m_dWidth + pNextLine->m_arConts.back()->m_dSpaceWidthMM); + pParagraph->m_dTop = pCurrLine->m_dBaselinePos - pCurrLine->m_dHeight - pCurrLine->m_dBaselineOffset; pParagraph->m_dSpaceBefore = dBeforeSpacingWithShapes + std::max(dCurrBeforeSpacing, 0.0);; dBeforeSpacingWithShapes = 0; pParagraph->m_dBaselinePos = pCurrLine->m_dBaselinePos; - /*if (fabs(dCurrRight - dNextRight) <= c_dTHE_STRING_X_PRECISION_MM) //предположение + if (fabs(dCurrRight - dNextRight) <= c_dTHE_STRING_X_PRECISION_MM) //предположение { pParagraph->m_eTextAlignmentType = CParagraph::TextAlignmentType_ByWidth; - }*/ + } + + //междустрочный интервал во всем параграфе + pParagraph->m_dHeight = pCurrLine->m_dHeight; //Объединим 2 строчки в параграф pParagraph->m_arLines.push_back(pCurrLine); @@ -933,6 +941,7 @@ namespace NSDocxRenderer pParagraph->m_arLines.push_back(new CTextLine(*pNextLine)); pParagraph->m_nNumLines++; + //сдвигаем рабочую точку pPrevLine = pCurrLine; pCurrLine = pNextLine; ++nNextIndex < m_arTextLine.size()-1? @@ -942,6 +951,7 @@ namespace NSDocxRenderer dPrevBeforeSpacing = dCurrBeforeSpacing; dCurrBeforeSpacing = pCurrLine->m_dBaselinePos - dPreviousStringOffset - pCurrLine->m_dHeight - pCurrLine->m_dBaselineOffset; dPreviousStringOffset = pCurrLine->m_dBaselinePos - pCurrLine->m_dBaselineOffset; + dCurrRight = dNextRight; if (pNextLine) @@ -950,18 +960,13 @@ namespace NSDocxRenderer dNextRight = m_dWidth - (pNextLine->m_dX + pNextLine->m_dWidth + pNextLine->m_arConts.back()->m_dSpaceWidthMM); } - //междустрочный интервал во всем параграфе - /*pParagraph->m_dHeight = pCurrLine->m_dHeight; - if (dCurrBeforeSpacing < 0) - { - pParagraph->m_dHeight += dCurrBeforeSpacing; - }*/ - pParagraph->m_dHeight = pCurrLine->m_dHeight + std::max(dCurrBeforeSpacing, 0.0); + //коррекция междустрочный интервал во всем параграфе + pParagraph->m_dHeight += std::max(dCurrBeforeSpacing, 0.0);; //проверим, подходят ли следующие строчки для текущего pParagraph while(pNextLine && fabs(pCurrLine->m_dHeight - pNextLine->m_dHeight) < c_dTHE_SAME_STRING_Y_PRECISION_MM && //высота строк должна быть примерно одинаковой - fabs(dCurrBeforeSpacing - dNextBeforeSpacing) < c_dTHE_SAME_STRING_Y_PRECISION_MM && //расстрояние между строк тоже одинаково + fabs(dCurrBeforeSpacing - dNextBeforeSpacing) < c_dLINE_DISTANCE_ERROR_MM && //расстрояние между строк тоже одинаково //(pCurrLine->m_eTextAlignmentType == pNextLine->m_eTextAlignmentType || //pNextLine->m_eTextAlignmentType == CParagraph::TextAlignmentType_ByLeftEdge) && ((fabs(pCurrLine->m_dX - pNextLine->m_dX) <= c_dTHE_STRING_X_PRECISION_MM && //у последующих строк нет отступа относительно предыдущей непервой строки diff --git a/DocxRenderer/test/main.cpp b/DocxRenderer/test/main.cpp index 9acb3eda0a..6f6bf413c4 100644 --- a/DocxRenderer/test/main.cpp +++ b/DocxRenderer/test/main.cpp @@ -91,13 +91,12 @@ int main(int argc, char *argv[]) //std::vector sSourceFiles = NSDirectory::GetFiles(L"C:\\Docs\\Рекомендуемая литература"); std::vector sSourceFiles; //Или добавляем любой нужный файл - //sSourceFiles.push_back(L"C:\\Users\\Alexander\\Desktop\\MSF_Lec1.pdf"); + sSourceFiles.push_back(L"C:\\Users\\Alexander\\Desktop\\MSF_Lec1.pdf"); sSourceFiles.push_back(L"C:\\Development\\test\\andersen_skazki_tom_1.pdf"); //перестал работать - текста нет ///sSourceFiles.push_back(L"C:\\Development\\test\\08 Правила дорожного движения РФ(108p).pdf"); sSourceFiles.push_back(L"C:\\Docs\\Рекомендуемая литература\\Мартин Фаулер - Рефакторинг.pdf"); - //sSourceFiles.push_back(L"C:\\Users\\Alexander\\Desktop\\MSF_Lec1.pdf"); - //sSourceFiles.push_back(L"C:\\Development\\test\\(1917) - Das geheimnisvolle Haus.pdf"); + sSourceFiles.push_back(L"C:\\Development\\test\\(1917) - Das geheimnisvolle Haus.pdf"); //sSourceFiles.push_back(L"C:\\Docs\\Рекомендуемая литература\\Embedded_Linux_system_design_and_development_ru.pdf"); //sSourceFiles.push_back(L"C:\\Docs\\Рекомендуемая литература\\Алан Купер - Психбольница в руках пациентов.pdf"); ///sSourceFiles.push_back(L"C:\\Docs\\Рекомендуемая литература\\Брюс Эккель - Философия C++.pdf");