sc/source/filter/html/htmlpars.cxx | 2 - sc/source/ui/docshell/impex.cxx | 6 ++-- svgio/inc/SvgNumber.hxx | 4 +-- svgio/inc/svgnode.hxx | 3 -- svgio/inc/svgtspannode.hxx | 2 - svgio/qa/cppunit/SvgImportTest.cxx | 34 ++++++++++++++++++++++++++ svgio/qa/cppunit/SvgNumberTest.cxx | 2 - svgio/qa/cppunit/data/dy_in_ems.svg | 7 +++++ svgio/qa/cppunit/data/dy_in_exs.svg | 7 +++++ svgio/source/svgreader/SvgNumber.cxx | 3 +- svgio/source/svgreader/svgnode.cxx | 17 +++---------- svgio/source/svgreader/svgstyleattributes.cxx | 8 +++--- svgio/source/svgreader/svgtspannode.cxx | 5 --- sw/qa/extras/odfexport/data/tdf160700.odt |binary sw/qa/extras/odfexport/odfexport2.cxx | 30 ++++++++++++++++++++++ sw/source/core/unocore/unoportenum.cxx | 3 ++ 16 files changed, 99 insertions(+), 34 deletions(-)
New commits: commit e4b31978049a5c96b7672ceabb1fdeef7048afec Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri Apr 19 00:34:28 2024 +0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Fri Apr 19 12:38:31 2024 +0200 tdf#160700: Avoid both bookmark-start and bookmark-end at the same index There is a special handling of CrossRefBookmark, which has no end position in the document model, but must span the whole paragraph, and end position is generated explicitly. Since commit 1d7ce421480d9170316533de03feb8d04eb5c767 (tdf#159438: when there's no frame, close previous bookmark first, 2024-01-30), end marks of an index are sorted before start marks of the same index, with the expectation that start / end marks represent non-empty span. Dun in case of empty paragraphs with a CrossRefBookmark, both start and end mark were emitted into the same index, and the new sorting resulted in the wrong order of the elements. Fix this by checking if the start index is less than node end, and don't handle CrossRefBookmark specially, if the check is negative. This writes a single text:bookmark, instead of a text:bookmark-start, followed by a text:bookmark-end. Change-Id: I533c4f7814edddc3cf24b1213490f251d60b2273 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166266 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166280 diff --git a/sw/qa/extras/odfexport/data/tdf160700.odt b/sw/qa/extras/odfexport/data/tdf160700.odt new file mode 100644 index 000000000000..bc1515da3f82 Binary files /dev/null and b/sw/qa/extras/odfexport/data/tdf160700.odt differ diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx index 49836082907c..f654821acf6a 100644 --- a/sw/qa/extras/odfexport/odfexport2.cxx +++ b/sw/qa/extras/odfexport/odfexport2.cxx @@ -21,6 +21,7 @@ #include <com/sun/star/text/XDocumentIndex.hpp> #include <com/sun/star/text/XDocumentIndexesSupplier.hpp> #include <com/sun/star/text/XTextColumns.hpp> +#include <com/sun/star/text/XTextField.hpp> #include <com/sun/star/text/XTextFieldsSupplier.hpp> #include <com/sun/star/text/XTextTable.hpp> #include <com/sun/star/text/XTextTablesSupplier.hpp> @@ -1343,6 +1344,35 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf159438) u"bookmark3"_ustr); } +CPPUNIT_TEST_FIXTURE(Test, testTdf160700) +{ + // Given a document with an empty numbered paragraph, and a cross-reference to it + loadAndReload("tdf160700.odt"); + + // Refresh fields and ensure cross-reference to numbered para is okay + auto xTextFieldsSupplier(mxComponent.queryThrow<text::XTextFieldsSupplier>()); + auto xFieldsAccess(xTextFieldsSupplier->getTextFields()); + + xFieldsAccess.queryThrow<util::XRefreshable>()->refresh(); + + auto xFields(xFieldsAccess->createEnumeration()); + CPPUNIT_ASSERT(xFields->hasMoreElements()); + auto xTextField(xFields->nextElement().queryThrow<text::XTextField>()); + // Save must not create markup with text:bookmark-end element before text:bookmark-start + // Withoud the fix, this would fail with + // - Expected: 1 + // - Actual : Error: Reference source not found + // i.e., the bookmark wasn't imported, and the field had no proper source + CPPUNIT_ASSERT_EQUAL(u"1"_ustr, xTextField->getPresentation(false)); + + xmlDocUniquePtr pXmlDoc = parseExport("content.xml"); + // Check that we export the bookmark in the empty paragraph as a single text:bookmark + // element. Another walid markup is text:bookmark-start followed by text:bookmark-end + // (in that order). The problem was, that text:bookmark-end was before text:bookmark-start. + assertXPathChildren(pXmlDoc, "//office:text/text:list/text:list-item/text:p"_ostr, 1); + assertXPath(pXmlDoc, "//office:text/text:list/text:list-item/text:p/text:bookmark"_ostr); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx index 494cec746865..709d79ef4d4b 100644 --- a/sw/source/core/unocore/unoportenum.cxx +++ b/sw/source/core/unocore/unoportenum.cxx @@ -150,8 +150,11 @@ namespace bool const hasOther = isExpanded && rStartPos != rEndPos; bool const bStartPosInNode = rStartPos.GetNode() == rOwnNode; bool const bEndPosInNode = rEndPos.GetNode() == rOwnNode; + // tdf#160700: Crossrefbookmarks only need separate start and end, when the start + // isn't in the end position (so in empty nodes, no need to handle them specially) sw::mark::CrossRefBookmark* const pCrossRefMark = !isExpanded && bStartPosInNode + && rStartPos.GetContentIndex() < rStartPos.GetContentNode()->Len() ? dynamic_cast<sw::mark::CrossRefBookmark*>(pBkmk) : nullptr; commit 23600b45a0cd643281cb2a934e5fe02b37c73788 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 9 13:56:13 2024 +0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Fri Apr 19 12:38:31 2024 +0200 tdf#160594: Use the recommended fallback of 0.5em for ex in font-size This fixes the error of identical treatment of em and ex in font-size, which violated https://drafts.csswg.org/css-values-4/#font-relative-length. The fix uses the fallback of 0.5em for ex, similar to the code used in SvgNumber::solveNonPercentage. A follow-up should implement the correct use of "x-height of the first available font". Change-Id: Id9d581994e158d629d9752299ad93ac7e9fe4cad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166234 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166261 diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index 7b1aafb41a2e..cfc83d425bb7 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -2101,6 +2101,22 @@ CPPUNIT_TEST_FIXTURE(Test, testDyInEms) assertXPath(pDocument, "//textsimpleportion[2]"_ostr, "y"_ostr, u"32"_ustr); } +CPPUNIT_TEST_FIXTURE(Test, testExs) +{ + // tdf#160594 given an SVG file with <tspan dy="3ex" style="font-size:1ex">: + xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/dy_in_exs.svg"); + + assertXPath(pDocument, "//textsimpleportion"_ostr, 2); + assertXPath(pDocument, "//textsimpleportion[1]"_ostr, "height"_ostr, u"16"_ustr); + + sal_Int32 nSize = getXPath(pDocument, "//textsimpleportion[2]"_ostr, "height"_ostr).toInt32(); + // Without the accompanying fix in place, this test would have failed with: + // - Expected less than: 16 + // - Actual : 16 + // i.e. the parent font-size was used, instead of its x-size. + CPPUNIT_ASSERT_LESS(sal_Int32(16), nSize); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svgio/qa/cppunit/data/dy_in_exs.svg b/svgio/qa/cppunit/data/dy_in_exs.svg new file mode 100644 index 000000000000..816a64a4586c --- /dev/null +++ b/svgio/qa/cppunit/data/dy_in_exs.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> + +<svg xmlns="http://www.w3.org/2000/svg" width="1in" height="1in" viewBox="0 0 100% 100%"> + + <text x="5" y="20" style="font-size:16px;font-family:Liberation Sans">foo + <tspan x="5" dy="3ex" style="font-size:1ex">bar</tspan></text> +</svg> \ No newline at end of file diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index 58bdb9add84b..50f72199e40b 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -2642,11 +2642,11 @@ namespace svgio::svgreader if(pSvgStyleAttributes) { const SvgNumber aParentNumber = pSvgStyleAttributes->getFontSizeNumber(); + double n = aParentNumber.getNumber() * maFontSizeNumber.getNumber(); + if (SvgUnit::ex == maFontSizeNumber.getUnit()) + n *= 0.5; // FIXME: use "x-height of the first available font" - return SvgNumber( - aParentNumber.getNumber() * maFontSizeNumber.getNumber(), - aParentNumber.getUnit(), - true); + return SvgNumber(n, aParentNumber.getUnit()); } } commit f0dc4bf464f831d02982c86d749fd8da10120500 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 9 13:03:07 2024 +0500 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Fri Apr 19 12:38:31 2024 +0200 tdf#160593: make sure to use current element's font size for em unit According to https://drafts.csswg.org/css-values-4/#font-relative-length em is "equal to the computed value of the font-size property of the element on which it is used". This means, that for an element that defines its own font-size, attributes like 'dy' using em refer to the new font-size, not to inherited font-size. Change-Id: Ie5a013df99a68edddf466e4c0ee5311f6219fcb2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166233 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166260 diff --git a/svgio/inc/SvgNumber.hxx b/svgio/inc/SvgNumber.hxx index 4d03335cf424..fe4ab8e2683e 100644 --- a/svgio/inc/SvgNumber.hxx +++ b/svgio/inc/SvgNumber.hxx @@ -37,8 +37,8 @@ class InfoProvider public: virtual ~InfoProvider() {} virtual basegfx::B2DRange getCurrentViewPort() const = 0; - /// return font size of node inherited from parents - virtual double getCurrentFontSizeInherited() const = 0; + /// return font size of node, either set here or inherited from parents + virtual double getCurrentFontSize() const = 0; /// return xheight of node inherited from parents virtual double getCurrentXHeightInherited() const = 0; }; diff --git a/svgio/inc/svgnode.hxx b/svgio/inc/svgnode.hxx index 16c1f50bc3db..98a444cba5fc 100644 --- a/svgio/inc/svgnode.hxx +++ b/svgio/inc/svgnode.hxx @@ -163,10 +163,9 @@ namespace svgio::svgreader /// InfoProvider support for %, em and ex values virtual basegfx::B2DRange getCurrentViewPort() const override; - virtual double getCurrentFontSizeInherited() const override; + virtual double getCurrentFontSize() const override; virtual double getCurrentXHeightInherited() const override; - double getCurrentFontSize() const; double getCurrentXHeight() const; /// Id access diff --git a/svgio/inc/svgtspannode.hxx b/svgio/inc/svgtspannode.hxx index 84033685d8f9..0740c3cece24 100644 --- a/svgio/inc/svgtspannode.hxx +++ b/svgio/inc/svgtspannode.hxx @@ -53,8 +53,6 @@ namespace svgio::svgreader virtual const SvgStyleAttributes* getSvgStyleAttributes() const override; virtual void parseAttribute(SVGToken aSVGToken, const OUString& aContent) override; - double getCurrentFontSize() const; - /// X content const SvgNumberVector& getX() const { return maX; } void setX(SvgNumberVector&& aX) { maX = std::move(aX); } diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index 2ec9df26418f..7b1aafb41a2e 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -2083,6 +2083,24 @@ CPPUNIT_TEST_FIXTURE(Test, testTspanFillOpacity) CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(70), nTransparence); } +CPPUNIT_TEST_FIXTURE(Test, testDyInEms) +{ + // tdf#160593 given an SVG file with <tspan dy="1.5em" style="font-size:0.5em">: + xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/dy_in_ems.svg"); + + assertXPath(pDocument, "//textsimpleportion"_ostr, 2); + assertXPath(pDocument, "//textsimpleportion[1]"_ostr, "y"_ostr, u"20"_ustr); + // Then make sure that the vertical offset is based on font-size of tspan, not of its parent. + // Given the parent's font-size is 16 px, the expected vertical offset is 1.5 * (16 * 0.5) = 12, + // which means that the resulting y is expected to be 20 + 12 = 32. + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 32 + // - Actual : 44 + // i.e. the offset was calculated as 1.5 multiplied by the parent's font-size of 16 px, + // not by the current tspan's half font-size. + assertXPath(pDocument, "//textsimpleportion[2]"_ostr, "y"_ostr, u"32"_ustr); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svgio/qa/cppunit/SvgNumberTest.cxx b/svgio/qa/cppunit/SvgNumberTest.cxx index f420a44b42fe..9b12e52bf956 100644 --- a/svgio/qa/cppunit/SvgNumberTest.cxx +++ b/svgio/qa/cppunit/SvgNumberTest.cxx @@ -38,7 +38,7 @@ public: return basegfx::B2DRange(0.0, 0.0, 0.0, 0.0); } - double getCurrentFontSizeInherited() const override { return 12.0; } + double getCurrentFontSize() const override { return 12.0; } double getCurrentXHeightInherited() const override { return 5.0; } }; diff --git a/svgio/qa/cppunit/data/dy_in_ems.svg b/svgio/qa/cppunit/data/dy_in_ems.svg new file mode 100644 index 000000000000..316239edf778 --- /dev/null +++ b/svgio/qa/cppunit/data/dy_in_ems.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> + +<svg xmlns="http://www.w3.org/2000/svg" width="1in" height="1in" viewBox="0 0 100% 100%"> + + <text x="5" y="20" style="font-size:16px;font-family:Liberation Sans">foo + <tspan x="5" dy="1.5em" style="font-size:0.5em">bar</tspan></text> +</svg> \ No newline at end of file diff --git a/svgio/source/svgreader/SvgNumber.cxx b/svgio/source/svgreader/SvgNumber.cxx index c1558f3e6451..4a48ffbfb4e9 100644 --- a/svgio/source/svgreader/SvgNumber.cxx +++ b/svgio/source/svgreader/SvgNumber.cxx @@ -35,8 +35,9 @@ double SvgNumber::solveNonPercentage(const InfoProvider& rInfoProvider) const switch (meUnit) { + // See https://drafts.csswg.org/css-values-4/#font-relative-length case SvgUnit::em: - return mfNumber * rInfoProvider.getCurrentFontSizeInherited(); + return mfNumber * rInfoProvider.getCurrentFontSize(); case SvgUnit::ex: return mfNumber * rInfoProvider.getCurrentXHeightInherited() * 0.5; case SvgUnit::px: diff --git a/svgio/source/svgreader/svgnode.cxx b/svgio/source/svgreader/svgnode.cxx index 7a45c681f19c..b881830a77a3 100644 --- a/svgio/source/svgreader/svgnode.cxx +++ b/svgio/source/svgreader/svgnode.cxx @@ -691,24 +691,15 @@ namespace { } } - double SvgNode::getCurrentFontSizeInherited() const - { - if(getParent()) - { - return getParent()->getCurrentFontSize(); - } - else - { - return 0.0; - } - } - double SvgNode::getCurrentFontSize() const { if(getSvgStyleAttributes()) return getSvgStyleAttributes()->getFontSizeNumber().solve(*this, NumberType::xcoordinate); - return getCurrentFontSizeInherited(); + if(getParent()) + return getParent()->getCurrentFontSize(); + + return 0.0; } double SvgNode::getCurrentXHeightInherited() const diff --git a/svgio/source/svgreader/svgtspannode.cxx b/svgio/source/svgreader/svgtspannode.cxx index 27d714e66a85..4e97c2bfc4cc 100644 --- a/svgio/source/svgreader/svgtspannode.cxx +++ b/svgio/source/svgreader/svgtspannode.cxx @@ -141,11 +141,6 @@ namespace svgio::svgreader } } - double SvgTspanNode::getCurrentFontSize() const - { - return getCurrentFontSizeInherited(); - } - } // end of namespace svgio::svgreader /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 0ef111343e3a78eaf1201926bea99a574751c6a9 Author: Laurent Balland <laurent.ball...@mailo.fr> AuthorDate: Mon Apr 15 18:43:35 2024 +0200 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Fri Apr 19 12:38:31 2024 +0200 tdf#129701 Follow-up of previous change According to comments in https://gerrit.libreoffice.org/c/core/+/163536 Follow-up of previous change Change-Id: Icd7b6798d6ef35ca9574125cd3d4c4d89044569c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166133 Tested-by: Jenkins Reviewed-by: Eike Rathke <er...@redhat.com> (cherry picked from commit 47187acee758680cda8086b6e295ef7beea3491b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166178 diff --git a/sc/source/ui/docshell/impex.cxx b/sc/source/ui/docshell/impex.cxx index 8e6315db9419..a61ee53d2526 100644 --- a/sc/source/ui/docshell/impex.cxx +++ b/sc/source/ui/docshell/impex.cxx @@ -1662,7 +1662,7 @@ bool ScImportExport::ExtText2Doc( SvStream& rStrm ) ScDocumentImport aDocImport(rDoc); do { - SCCOL nLastCol = nEndCol; // tdf#129701 preserve value of nEndCol + const SCCOL nLastCol = nEndCol; // tdf#129701 preserve value of nEndCol for( ;; ) { aLine = ReadCsvLine(rStrm, !bFixed, aSeps, cStr, cDetectSep); @@ -1784,15 +1784,15 @@ bool ScImportExport::ExtText2Doc( SvStream& rStrm ) aTransliteration, aCalendar, pEnglishTransliteration.get(), pEnglishCalendar.get()); } + ++nCol; if (bIsLastColEmpty) { bIsLastColEmpty = false; // toggle to stop } else { - ++nCol; // tdf#129701 detect if there is a last empty column when we need it - bIsLastColEmpty = !(*p) && !bSkipEmptyCells && !bDetermineRange && nCol == nLastCol; + bIsLastColEmpty = (nCol == nLastCol) && !(*p) && !bSkipEmptyCells && !bDetermineRange; } } commit c1cff695447edd00df6a3775848227c06892906f Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Apr 16 17:34:35 2024 +0100 Commit: Andras Timar <andras.ti...@collabora.com> CommitDate: Fri Apr 19 12:38:31 2024 +0200 ofz#68081 keep within bounds Change-Id: Ib7f11f2447d5a2cc6b9b559727f2a0127c15913e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166154 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit c09c61f5e3f7207006c3a26f5a79fabc29600350) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166098 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index b5af7d9f14ac..47eb022ba3bc 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -909,7 +909,7 @@ void ScHTMLLayoutParser::Colonize( ScEEParseEntry* pE ) { // Replaced nCol = pE->nCol - nColCntStart; SCCOL nCount = static_cast<SCCOL>(xLocalColOffset->size()); - if ( nCol < nCount ) + if (nCol >= 0 && nCol < nCount) nColOffset = static_cast<sal_uInt16>((*xLocalColOffset)[nCol]); else nColOffset = static_cast<sal_uInt16>((*xLocalColOffset)[nCount - 1]);