bin/find-can-be-private-symbols.functions.results | 5 configure.ac | 4 cui/source/tabpages/paragrph.cxx | 10 cui/uiconfig/ui/optviewpage.ui | 3 dbaccess/source/ui/relationdesign/RTableConnectionData.cxx | 5 dbaccess/source/ui/relationdesign/RelationTableView.cxx | 10 download.lst | 8 drawinglayer/source/primitive2d/textlayoutdevice.cxx | 67 drawinglayer/source/processor2d/vclprocessor2d.cxx | 28 editeng/source/editeng/impedit3.cxx | 2 extras/source/tipoftheday/formdocuments.svg | 2 include/drawinglayer/primitive2d/textlayoutdevice.hxx | 2 include/formula/tokenarray.hxx | 2 include/svl/numformat.hxx | 31 include/svl/zformat.hxx | 12 include/vcl/outdev.hxx | 7 include/vcl/vcllayout.hxx | 5 odk/docs/install.html | 2 readlicense_oo/license/CREDITS.fodt | 3327 ++++++------- sc/Module_sc.mk | 7 sc/inc/interpretercontext.hxx | 4 sc/qa/uitest/pasteSpecial/tdf160765.py | 109 sc/qa/unit/data/ods/tdf160329_sortWithHiddenRows.ods |binary sc/qa/unit/scshapetest.cxx | 37 sc/source/core/data/queryevaluator.cxx | 2 sc/source/core/data/table3.cxx | 78 sc/source/core/tool/interpr4.cxx | 49 sc/source/ui/miscdlgs/inscodlg.cxx | 4 sc/source/ui/navipi/content.cxx | 2 sc/source/ui/view/viewfun3.cxx | 3 sc/uiconfig/scalc/ui/conditionalentry.ui | 343 - sd/qa/unit/data/odg/adjust-to-contour.fodg | 52 sd/qa/unit/layout-tests.cxx | 48 sfx2/source/doc/objstor.cxx | 6 svgio/inc/svgcharacternode.hxx | 8 svgio/inc/svgstyleattributes.hxx | 8 svgio/qa/cppunit/SvgImportTest.cxx | 150 svgio/qa/cppunit/data/contextStroke.svg | 14 svgio/qa/cppunit/data/tdf160773.svg | 5 svgio/source/svgreader/svgcharacternode.cxx | 115 svgio/source/svgreader/svgdocumenthandler.cxx | 83 svgio/source/svgreader/svgmarkernode.cxx | 2 svgio/source/svgreader/svgstyleattributes.cxx | 38 svl/source/items/itemset.cxx | 18 svl/source/numbers/zforlist.cxx | 15 svl/source/numbers/zformat.cxx | 12 svx/source/dialog/svxruler.cxx | 2 sw/qa/core/text/data/Broken indent demo.odt |binary sw/qa/core/text/data/tdf156146.fodt | 281 + sw/qa/core/text/text.cxx | 62 sw/qa/extras/odfexport/odfexport2.cxx | 6 sw/qa/extras/uiwriter/data/table-in-table.fodt | 29 sw/qa/extras/uiwriter/uiwriter9.cxx | 14 sw/qa/uitest/writer_tests2/formatParagraph.py | 2 sw/source/core/crsr/crsrsh.cxx | 12 sw/source/core/text/inftxt.hxx | 6 sw/source/core/text/itratr.hxx | 2 sw/source/core/text/itrtxt.hxx | 2 sw/source/filter/html/htmlctxt.cxx | 3 sysui/desktop/menus/calc.desktop | 2 sysui/desktop/menus/draw.desktop | 2 sysui/desktop/menus/impress.desktop | 2 sysui/desktop/menus/math.desktop | 2 sysui/desktop/menus/writer.desktop | 2 vcl/inc/qt5/QtTransferable.hxx | 31 vcl/qa/cppunit/graphicfilter/filters-webp-test.cxx | 12 vcl/qa/cppunit/pdfexport/pdfexport2.cxx | 6 vcl/qt5/QtClipboard.cxx | 2 vcl/qt5/QtTransferable.cxx | 81 vcl/skia/gdiimpl.cxx | 2 vcl/source/app/svapp.cxx | 1 vcl/source/bitmap/BitmapEx.cxx | 11 vcl/source/filter/webp/reader.cxx | 4 vcl/source/gdi/pdfwriter_impl.cxx | 14 vcl/source/gdi/sallayout.cxx | 33 vcl/source/outdev/map.cxx | 8 vcl/source/outdev/text.cxx | 38 vcl/win/gdi/DWriteTextRenderer.cxx | 11 xmloff/source/text/XMLTextListBlockContext.hxx | 1 xmloff/source/text/txtimp.cxx | 64 80 files changed, 3249 insertions(+), 2245 deletions(-)
New commits: commit 470f00694ac42fd07a55d6fbea5a56a28791fcc0 Author: Aron Budea <aron.bu...@collabora.com> AuthorDate: Wed May 8 13:23:00 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 13:23:00 2024 +0200 Bump version to 24.04.2.1 Change-Id: I27a048323e6f65273688955bdac97dd4f312d88f diff --git a/configure.ac b/configure.ac index 745788dc5525..f788bb346a2b 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ dnl in order to create a configure script. # several non-alphanumeric characters, those are split off and used only for the # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no idea. -AC_INIT([Collabora Office],[24.04.1.4],[],[],[https://collaboraoffice.com/]) +AC_INIT([Collabora Office],[24.04.2.1],[],[],[https://collaboraoffice.com/]) dnl libnumbertext needs autoconf 2.68, but that can pick up autoconf268 just fine if it is installed dnl whereas aclocal (as run by autogen.sh) insists on using autoconf and fails hard commit 56097e5efdb85b3846a0c2536d3e45c0ab566b87 Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Thu Apr 25 15:52:29 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:58 2024 +0200 svx: Avoid divide by 0 See https://crashreport.libreoffice.org/stats/signature/SvxRuler::UpdateTabs() Change-Id: Ie08c54d1a1b40bcc42da9f81c893f496fff433a8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166626 Tested-by: Jenkins Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit 90548039f09d4bc773bf6879a62d544adfa175db) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166674 Reviewed-by: Aron Budea <aron.bu...@collabora.com> (cherry picked from commit 35c0afcf0a0428670e3e1998f222440b504ae0c8) diff --git a/svx/source/dialog/svxruler.cxx b/svx/source/dialog/svxruler.cxx index 6323583fd271..17c4edaa930d 100644 --- a/svx/source/dialog/svxruler.cxx +++ b/svx/source/dialog/svxruler.cxx @@ -1033,7 +1033,7 @@ void SvxRuler::UpdateTabs() lCurrentDefTabDist = mxTabStopItem->GetDefaultDistance(); tools::Long nDefTabDist = ConvertHPosPixel(lCurrentDefTabDist); - const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > lRightIndent + const sal_uInt16 nDefTabBuf = lPosPixel > lRightIndent || lLastTab > lRightIndent || nDefTabDist == 0 ? 0 : static_cast<sal_uInt16>( (lRightIndent - lPosPixel) / nDefTabDist ); commit 1c06adec8df9c6add4681d8c2554cde765e91144 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sun May 5 20:54:59 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:48 2024 +0200 wrong ScContentTree::SelectEntryByName early return condition Change-Id: I974f5aea545a80b0e48b50e2a2eae0729ff59691 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167174 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins (cherry picked from commit 18b70ec7d9c4a0288f206cb64708f87a83789c00) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167085 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> (cherry picked from commit fb7e3ebf22a120fa0055d556616aeb69abe49bec) diff --git a/sc/source/ui/navipi/content.cxx b/sc/source/ui/navipi/content.cxx index d16f61411016..5694fe40fe84 100644 --- a/sc/source/ui/navipi/content.cxx +++ b/sc/source/ui/navipi/content.cxx @@ -1451,7 +1451,7 @@ void ScContentTree::SelectEntryByName(const ScContentId nRoot, std::u16string_vi { weld::TreeIter* pParent = m_aRootNodes[nRoot].get(); - if (pParent || !m_xTreeView->iter_has_child(*pParent)) + if (!pParent || !m_xTreeView->iter_has_child(*pParent)) return; std::unique_ptr<weld::TreeIter> xEntry(m_xTreeView->make_iterator(pParent)); commit 428767c907b476ffcd5573abbdef58a08289729f Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Tue Apr 23 11:54:47 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:40 2024 +0200 tdf#159661, tdf#160773: svgio: Add unittest Change-Id: I2d0b96f13e02ac81b97ea347889c76770c22a989 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166509 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167053 (cherry picked from commit b2dc48571714a84b1eeff127e86c07b29b579e43) diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index dc900b1eee1e..48b8d89bfeee 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -1976,6 +1976,22 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156837) assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, "3"); } +CPPUNIT_TEST_FIXTURE(Test, testTdf160773) +{ + xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/tdf160773.svg"); + + // tdf#160773 Check there is a rectangle + assertXPath(pDocument, "/primitive2D/transform/mask/transform/polypolygoncolor"_ostr, "color"_ostr, "#ff0000"); + + // tdf#159661 Check there is text in the right position + assertXPath(pDocument, "/primitive2D/transform/mask/transform/textsimpleportion"_ostr, 1); + assertXPath(pDocument, "/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "x"_ostr, "0"); + assertXPath(pDocument, "/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "y"_ostr, "0"); + assertXPath(pDocument, "/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "height"_ostr, "0"); + assertXPath(pDocument, "/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "width"_ostr, "0"); + assertXPath(pDocument, "/primitive2D/transform/mask/transform/textsimpleportion"_ostr, "text"_ostr, "Red"); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf156271) { Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/tdf156271.svg"); diff --git a/svgio/qa/cppunit/data/tdf160773.svg b/svgio/qa/cppunit/data/tdf160773.svg new file mode 100644 index 000000000000..812c0824862c --- /dev/null +++ b/svgio/qa/cppunit/data/tdf160773.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" ?> +<svg width="600px" height="600px" viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg"> + <text x="0" y="0.5" font-size="0.2px" dominant-baseline="middle" >Red</text> + <rect x="0.05" y="0.05" fill="#f00" width="0.36" height="0.242" /> +</svg> commit 5140abd2c94b96f2a32f0f7416ae79239a2af187 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Fri May 3 14:14:26 2024 +0500 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:32 2024 +0200 tdf#152906: use correct Y offset GetEditCursor now returns the position relative to the line, not to the whole text. In ImpEditEngine::CreateLines, its use wasn't fixed, and so the Y position of all lines in the calculation was the same, thus adjusting to the same contour's horizontal stripe. Change-Id: I16362bab47f3064281eefb45a12834d836a8ada3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167042 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/+/167188 (cherry picked from commit 9f5664f4d34e8f04cc18dc252cad4b3b853db882) diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 464e9ed07550..32875bd76f0b 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -929,7 +929,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { GetTextRanger()->SetVertical( IsEffectivelyVertical() ); - tools::Long nTextY = nStartPosY + GetEditCursor( pParaPortion, pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top(); + tools::Long nTextY = nCurrentPosY + GetEditCursor( pParaPortion, pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top(); if ( !bSameLineAgain ) { SeekCursor( pNode, nTmpPos+1, aTmpFont ); diff --git a/sd/qa/unit/data/odg/adjust-to-contour.fodg b/sd/qa/unit/data/odg/adjust-to-contour.fodg new file mode 100644 index 000000000000..a5ec6fed74fc --- /dev/null +++ b/sd/qa/unit/data/odg/adjust-to-contour.fodg @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.graphics"> + <office:font-face-decls> + <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:punctuation-wrap="simple" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + </style:default-style> + <style:style style:name="standard" style:family="graphic"> + <style:graphic-properties draw:stroke="solid" svg:stroke-width="0cm" draw:marker-start-width="0.2cm" draw:marker-start-center="false" draw:marker-end-width="0.2cm" draw:marker-end-center="false" draw:fill="solid" draw:textarea-horizontal-align="justify" fo:padding-top="0" fo:padding-bottom="0" fo:padding-left="0" fo:padding-right="0" fo:wrap-option="wrap" draw:shadow="hidden" draw:shadow-offset-x="0.2cm" draw:shadow-offset-y="0.2cm" draw:shadow-color="#808080"/> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" fo:line-height="100%" fo:text-indent="0cm"/> + <style:text-properties fo:font-variant="normal" fo:text-transform="none" style:use-window-font-color="true" style:text-outline="false" style:text-line-through-style="none" style:text-line-through-type="none" style:font-name="Liberation Sans" fo:font-size="18pt" fo:font-style="normal" fo:text-shadow="none" style:text-underline-style="none" fo:font-weight="normal" style:letter-kerning="true" style:text-emphasize="none" style:font-relief="none" style:text-overline-style="none" style:text-overline-color="font-color"/> + </style:style> + </office:styles> + <office:automatic-styles> + <style:page-layout style:name="PM0"> + <style:page-layout-properties fo:margin-top="0" fo:margin-bottom="0" fo:margin-left="0" fo:margin-right="0" fo:page-width="21cm" fo:page-height="29.7cm" style:print-orientation="portrait"/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"/> + <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard"> + <style:graphic-properties draw:textarea-vertical-align="middle" draw:fit-to-contour="true"/> + </style:style> + <style:style style:name="P1" style:family="paragraph"> + <style:paragraph-properties fo:text-align="center"/> + <style:text-properties fo:language="zxx" fo:country="none"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <draw:layer-set> + <draw:layer draw:name="layout"/> + <draw:layer draw:name="background"/> + <draw:layer draw:name="backgroundobjects"/> + <draw:layer draw:name="controls"/> + <draw:layer draw:name="measurelines"/> + </draw:layer-set> + <style:master-page style:name="Default" style:page-layout-name="PM0" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:drawing> + <draw:page draw:name="page1" draw:style-name="dp1" draw:master-page-name="Default"> + <draw:ellipse draw:style-name="gr1" draw:layer="layout" svg:width="13cm" svg:height="13cm" svg:x="4cm" svg:y="8cm"> + <text:p text:style-name="P1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. Curabitur dignissim sapien quis cursus egestas. Donec blandit auctor arcu, nec pellentesque eros molestie eget. In consectetur aliquam hendrerit. Sed cursus mauris vitae ligula pellentesque, non pellentesque urna aliquet. Fusce placerat mauris enim, nec rutrum purus semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce pellentesque est orci.</text:p> + </draw:ellipse> + </draw:page> + </office:drawing> + </office:body> +</office:document> \ No newline at end of file diff --git a/sd/qa/unit/layout-tests.cxx b/sd/qa/unit/layout-tests.cxx index a93584b62f67..9be1ce154bc6 100644 --- a/sd/qa/unit/layout-tests.cxx +++ b/sd/qa/unit/layout-tests.cxx @@ -380,6 +380,54 @@ CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf112594) u"11\u202f\u1824"_ustr); } +CPPUNIT_TEST_FIXTURE(SdLayoutTest, testTdf152906_AdjustToContour) +{ + // Test that the text adjusts to contour properly + + constexpr OUString sText + = u"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum consequat mi quis " + "pretium semper. Proin luctus orci ac neque venenatis, quis commodo dolor posuere. " + "Curabitur dignissim sapien quis cursus egestas. Donec blandit auctor arcu, nec " + "pellentesque eros molestie eget. In consectetur aliquam hendrerit. Sed cursus mauris " + "vitae ligula pellentesque, non pellentesque urna aliquet. Fusce placerat mauris enim, " + "nec rutrum purus semper vel. Praesent tincidunt neque eu pellentesque pharetra. Fusce " + "pellentesque est orci."_ustr; + + // index, length, x, y + const std::tuple<int, int, int, int> strings[] = { + { 0, 6, 9600, 8647 }, // Lorem + { 6, 22, 7572, 9358 }, // ipsum dolor sit amet, + { 28, 29, 6776, 10069 }, // consectetur adipiscing elit. + { 57, 29, 6300, 10780 }, // Vestibulum consequat mi quis + { 86, 37, 5453, 11491 }, // pretium semper. Proin luctus orci ac + { 123, 36, 5136, 12202 }, // neque venenatis, quis commodo dolor + { 159, 41, 4765, 12913 }, // posuere. Curabitur dignissim sapien quis + { 200, 43, 4482, 13624 }, // cursus egestas. Donec blandit auctor arcu, + { 243, 40, 4977, 14335 }, // nec pellentesque eros molestie eget. In + { 283, 42, 4554, 15046 }, // consectetur aliquam hendrerit. Sed cursus + { 325, 38, 5364, 15757 }, // mauris vitae ligula pellentesque, non + { 363, 42, 4693, 16468 }, // pellentesque urna aliquet. Fusce placerat + { 405, 37, 5049, 17179 }, // mauris enim, nec rutrum purus semper + { 442, 33, 5963, 17890 }, // vel. Praesent tincidunt neque eu + { 475, 29, 6389, 18601 }, // pellentesque pharetra. Fusce + { 504, 22, 7500, 19312 }, // pellentesque est orci. + }; + + xmlDocUniquePtr pXmlDoc = load("odg/adjust-to-contour.fodg"); + + assertXPath(pXmlDoc, "/metafile/push[1]/push[1]/textarray"_ostr, std::size(strings)); + for (size_t i = 0; i < std::size(strings); ++i) + { + const auto & [ index, length, x, y ] = strings[i]; + OString sXPath = "/metafile/push[1]/push[1]/textarray[" + OString::number(i + 1) + "]"; + assertXPathContent(pXmlDoc, sXPath + "/text", sText); + assertXPath(pXmlDoc, sXPath, "index"_ostr, OUString::number(index)); + assertXPath(pXmlDoc, sXPath, "length"_ostr, OUString::number(length)); + assertXPath(pXmlDoc, sXPath, "x"_ostr, OUString::number(x)); + assertXPath(pXmlDoc, sXPath, "y"_ostr, OUString::number(y)); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit dcd9cf8d045a43f187067c5d709505b1ec382f9c Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sat Apr 13 20:42:16 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:23 2024 +0200 Related: tdf#160056 1 entry is more common than no entries Change-Id: I78fe8969120f894cf5c0a71fb61611af2d203d18 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166065 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit 7f2283c2986ff94766cc1d2c076fb34a2c88a31a) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166302 Reviewed-by: Eike Rathke <er...@redhat.com> (cherry picked from commit 46bd13a55492adef4bf95133d7123494a62f549a) diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index 66780cb581cb..fd9cbb1dddee 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -1891,11 +1891,8 @@ static void isMiss() sal_uInt16 WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const { - if (empty()) - return INVALID_WHICHPAIR_OFFSET; - // special case for single entry - happens often e.g. UI stuff - if (1 == m_size) + if (m_size == 1) { if( m_pairs->first <= nWhich && nWhich <= m_pairs->second ) return nWhich - m_pairs->first; @@ -1904,6 +1901,9 @@ sal_uInt16 WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const return INVALID_WHICHPAIR_OFFSET; } + if (m_size == 0) + return INVALID_WHICHPAIR_OFFSET; + // check if nWhich is inside last successfully used WhichPair if (INVALID_WHICHPAIR_OFFSET != m_aLastWhichPairOffset && m_aLastWhichPairFirst <= nWhich @@ -1949,12 +1949,8 @@ sal_uInt16 WhichRangesContainer::getOffsetFromWhich(sal_uInt16 nWhich) const sal_uInt16 WhichRangesContainer::getWhichFromOffset(sal_uInt16 nOffset) const { - // check for empty, if yes, return null which is an invalid WhichID - if (empty()) - return 0; - // special case for single entry - happens often e.g. UI stuff - if (1 == m_size) + if (m_size == 1) { if (nOffset <= m_pairs->second - m_pairs->first) return m_pairs->first + nOffset; @@ -1963,6 +1959,10 @@ sal_uInt16 WhichRangesContainer::getWhichFromOffset(sal_uInt16 nOffset) const return 0; } + // check for empty, if yes, return null which is an invalid WhichID + if (m_size == 0) + return 0; + // check if nWhich is inside last successfully used WhichPair if (INVALID_WHICHPAIR_OFFSET != m_aLastWhichPairOffset) { commit 14620a5113c817f9888a18e08d4bd7919cf80a75 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Fri Apr 12 12:24:06 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:15 2024 +0200 Related: tdf#160056 don't call GetParamCount twice GetParamCount: 290ms -> 175ms Change-Id: Ic3a26b1e8035744dcab2da69a8ebd3b29dd2160a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166031 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit 030b655963c182693c7b657dc6aa4d2fe85c17c6) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166301 Reviewed-by: Eike Rathke <er...@redhat.com> (cherry picked from commit 34126d6fceb054b7ba05ceeae76e32c89fac580f) diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 597f13c691f2..b3a2f8786f22 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4048,8 +4048,9 @@ StackVar ScInterpreter::Interpret() (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix) { // Path already calculated, reuse result. - if (sp >= pCur->GetParamCount()) - nStackBase = sp - pCur->GetParamCount(); + const sal_uInt8 nParamCount = pCur->GetParamCount(); + if (sp >= nParamCount) + nStackBase = sp - nParamCount; else { SAL_WARN("sc.core", "Stack anomaly with calculated path at " @@ -4057,7 +4058,7 @@ StackVar ScInterpreter::Interpret() << " " << aPos.Format( ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc) << " eOp: " << static_cast<int>(eOp) - << " params: " << static_cast<int>(pCur->GetParamCount()) + << " params: " << static_cast<int>(nParamCount) << " nStackBase: " << nStackBase << " sp: " << sp); nStackBase = sp; assert(!"underflow"); @@ -4086,18 +4087,22 @@ StackVar ScInterpreter::Interpret() eOp = ocNone; // JumpMatrix created nStackBase = sp; } - else if (sp >= pCur->GetParamCount()) - nStackBase = sp - pCur->GetParamCount(); else { - SAL_WARN("sc.core", "Stack anomaly at " << aPos.Tab() << "," << aPos.Col() << "," << aPos.Row() - << " " << aPos.Format( - ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc) - << " eOp: " << static_cast<int>(eOp) - << " params: " << static_cast<int>(pCur->GetParamCount()) - << " nStackBase: " << nStackBase << " sp: " << sp); - nStackBase = sp; - assert(!"underflow"); + const sal_uInt8 nParamCount = pCur->GetParamCount(); + if (sp >= nParamCount) + nStackBase = sp - nParamCount; + else + { + SAL_WARN("sc.core", "Stack anomaly at " << aPos.Tab() << "," << aPos.Col() << "," << aPos.Row() + << " " << aPos.Format( + ScRefFlags::VALID | ScRefFlags::FORCE_DOC | ScRefFlags::TAB_3D, &mrDoc) + << " eOp: " << static_cast<int>(eOp) + << " params: " << static_cast<int>(nParamCount) + << " nStackBase: " << nStackBase << " sp: " << sp); + nStackBase = sp; + assert(!"underflow"); + } } } commit 53cb51744a428c070db266056e56fa52365785f8 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sat Apr 13 16:35:28 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:13:07 2024 +0200 Related: tdf#160056 don't set nVal twice Change-Id: I0da3e0c7f18271f6104d52b50d65e96564650b8b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166054 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit 63b237e1e8147f54e6d4db4671f612a656200e2f) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166300 Reviewed-by: Eike Rathke <er...@redhat.com> (cherry picked from commit 9757290668b50827ab22597a73a4850ebf3f6521) diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 8764a7674a85..597f13c691f2 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -2099,7 +2099,7 @@ double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat) double ScInterpreter::GetDouble() { - double nVal(0.0); + double nVal; switch( GetRawStackType() ) { case svDouble: @@ -2134,13 +2134,16 @@ double ScInterpreter::GetDouble() { ScExternalRefCache::TokenRef pToken; PopExternalSingleRef(pToken); - if (nGlobalError == FormulaError::NONE) + if (nGlobalError != FormulaError::NONE) { - if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell) - nVal = pToken->GetDouble(); - else - nVal = ConvertStringToValue( pToken->GetString().getString()); + nVal = 0.0; + break; } + + if (pToken->GetType() == svDouble || pToken->GetType() == svEmptyCell) + nVal = pToken->GetDouble(); + else + nVal = ConvertStringToValue( pToken->GetString().getString()); } break; case svExternalDoubleRef: @@ -2148,7 +2151,10 @@ double ScInterpreter::GetDouble() ScMatrixRef pMat; PopExternalDoubleRef(pMat); if (nGlobalError != FormulaError::NONE) + { + nVal = 0.0; break; + } nVal = GetDoubleFromMatrix(pMat); } commit da60a27ac06ddc1c51a5eec5e8bc5c4f6e3b6f80 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sat Apr 13 10:56:37 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:59 2024 +0200 Related: tdf#160056 all maTokens are FormulaTypedDoubleToken* Change-Id: I6eacaf58c25ef9c5cb930a79177471c79a6a26c0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166047 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> (cherry picked from commit adbbe732e7ed7f3a749e04f1d9023989c972ec22) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166299 Reviewed-by: Eike Rathke <er...@redhat.com> (cherry picked from commit bc7198d47b4d1aef7a346c3f939122c9c764eeda) diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx index 5b3a85ab24d9..c43e9c0b6892 100644 --- a/sc/inc/interpretercontext.hxx +++ b/sc/inc/interpretercontext.hxx @@ -19,7 +19,7 @@ namespace formula { -class FormulaToken; +class FormulaTypedDoubleToken; } #define TOKEN_CACHE_SIZE 8 @@ -44,7 +44,7 @@ struct ScInterpreterContext { const ScDocument* mpDoc; size_t mnTokenCachePos; - std::vector<formula::FormulaToken*> maTokens; + std::vector<formula::FormulaTypedDoubleToken*> maTokens; std::vector<DelayedSetNumberFormat> maDelayedSetNumberFormat; std::unique_ptr<ScLookupCacheMap> mxScLookupCache; // cache for lookups like VLOOKUP and MATCH // Allocation cache for "aConditions" array in ScInterpreter::IterateParameterIfs() commit ad9e4e1869c109fb7821fb9a7ec1eb957891c8bd Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Tue Mar 12 20:38:35 2024 +0000 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:51 2024 +0200 Related: tdf#160056 various functions and objects that can be const this formatter can be const Change-Id: I2cd83140585e0b7027bb1c165a8d59e51cbbaad0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164728 Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> SvNumberformat::ImpGetFractionOfSecondString can be const Change-Id: If7a31f8b3667d9a6b8719553567211071bd2d631 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164774 Tested-by: Jenkins Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> ImpIsEntry can be const Change-Id: Id229344a68925a1bde84f2b4aad46cfc5f01b797 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164769 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> SvNumberformat::ImpGetLogicalOutput can be const Change-Id: I847e5de84f0636b5a169f383e319a6b8707cc31f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164773 Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> SvNumberFormatter::GetUserDefColor can be const Change-Id: If499e28e5ac69018b35b475a73ecb2dc4b78dad6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164786 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> These methods can be const too Change-Id: Iaef46216dac6584f57b7933d658384f54d0a4544 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164772 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166125 Reviewed-by: Eike Rathke <er...@redhat.com> (cherry picked from commit e3e9d51c2d4bed475f9848c62c7b0e5c72d5e125) diff --git a/include/svl/numformat.hxx b/include/svl/numformat.hxx index bf31ff22b605..2ebed94959cc 100644 --- a/include/svl/numformat.hxx +++ b/include/svl/numformat.hxx @@ -62,7 +62,7 @@ public: /// Set CallBack to ColorTable void SetColorLink(const Link<sal_uInt16, Color*>& rColorTableCallBack); /// Do the CallBack to ColorTable - Color* GetUserDefColor(sal_uInt16 nIndex); + Color* GetUserDefColor(sal_uInt16 nIndex) const; /// Change language/country, also input and format scanner void ChangeIntl(LanguageType eLnge); @@ -627,7 +627,7 @@ private: // Test whether format code already exists, then return index key, // otherwise NUMBERFORMAT_ENTRY_NOT_FOUND SVL_DLLPRIVATE sal_uInt32 ImpIsEntry(std::u16string_view rString, sal_uInt32 CLOffset, - LanguageType eLnge); + LanguageType eLnge) const; // Create builtin formats for language/country if necessary, return CLOffset SVL_DLLPRIVATE sal_uInt32 ImpGenerateCL(LanguageType eLnge); diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx index 1fa52c3384a2..b4d7ddb0ac29 100644 --- a/include/svl/zformat.hxx +++ b/include/svl/zformat.hxx @@ -638,7 +638,7 @@ private: sal_uInt16 j, sal_uInt16 nIx, sal_Int32 nDigCnt, - bool bAddDecSep = true ); + bool bAddDecSep = true ) const; // Helper function to fill in the group (AKA thousand) separators // or to skip additional digits @@ -647,14 +647,14 @@ private: sal_Int32& k, sal_uInt16 nIx, sal_Int32 & nDigitCount, - utl::DigitGroupingIterator & ); + utl::DigitGroupingIterator & ) const; SVL_DLLPRIVATE bool ImpDecimalFill( OUStringBuffer& sStr, double& rNumber, sal_Int32 nDecPos, sal_uInt16 j, sal_uInt16 nIx, - bool bInteger ); + bool bInteger ) const; /** Calculate each element of fraction: * integer part, numerator part, denominator part @@ -701,11 +701,11 @@ private: SVL_DLLPRIVATE bool ImpGetLogicalOutput( double fNumber, sal_uInt16 nIx, - OUStringBuffer& OutString ); + OUStringBuffer& OutString ) const; SVL_DLLPRIVATE bool ImpGetNumberOutput( double fNumber, sal_uInt16 nIx, - OUStringBuffer& OutString ); + OUStringBuffer& OutString ) const; SVL_DLLPRIVATE void ImpCopyNumberformat( const SvNumberformat& rFormat ); @@ -731,7 +731,7 @@ private: // nFractionDecimals, unless nMinimumInputLineDecimals>0 is given for input // line string where extra trailing "0" are discarded. SVL_DLLPRIVATE sal_uInt16 ImpGetFractionOfSecondString( OUStringBuffer& rBuf, double fFractionOfSecond, - int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, sal_uInt16 nMinimumInputLineDecimals ); + int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, sal_uInt16 nMinimumInputLineDecimals ) const; // transliterate according to NativeNumber SVL_DLLPRIVATE OUString impTransliterateImpl(const OUString& rStr, const SvNumberNatNum& rNum) const; diff --git a/sc/source/core/data/queryevaluator.cxx b/sc/source/core/data/queryevaluator.cxx index a8a08d9edfd9..174e1e0989c7 100644 --- a/sc/source/core/data/queryevaluator.cxx +++ b/sc/source/core/data/queryevaluator.cxx @@ -244,7 +244,7 @@ std::pair<bool, bool> ScQueryEvaluator::compareByValue(const ScRefCellValue& rCe nNumFmt = getNumFmt(nCol, nRow); if (nNumFmt) { - SvNumberFormatter* pFormatter + const SvNumberFormatter* pFormatter = mpContext ? mpContext->GetFormatTable() : mrDoc.GetFormatTable(); const SvNumberformat* pEntry = pFormatter->GetEntry(nNumFmt); if (pEntry) diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx index c96653460d95..a75c932a2c1c 100644 --- a/svl/source/numbers/zforlist.cxx +++ b/svl/source/numbers/zforlist.cxx @@ -376,7 +376,7 @@ void SvNumberFormatter::SetColorLink( const Link<sal_uInt16,Color*>& rColorTable aColorLink = rColorTableCallBack; } -Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex) +Color* SvNumberFormatter::GetUserDefColor(sal_uInt16 nIndex) const { ::osl::MutexGuard aGuard( GetInstanceMutex() ); if( aColorLink.IsSet() ) @@ -998,7 +998,7 @@ sal_uInt32 SvNumberFormatter::ImpGetCLOffset(LanguageType eLnge) const sal_uInt32 SvNumberFormatter::ImpIsEntry(std::u16string_view rString, sal_uInt32 nCLOffset, - LanguageType eLnge) + LanguageType eLnge) const { sal_uInt32 res = NUMBERFORMAT_ENTRY_NOT_FOUND; auto it = aFTable.find( nCLOffset); @@ -1017,7 +1017,6 @@ sal_uInt32 SvNumberFormatter::ImpIsEntry(std::u16string_view rString, return res; } - SvNumberFormatTable& SvNumberFormatter::GetFirstEntryTable( SvNumFormatType& eType, sal_uInt32& FIndex, diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx index 313a59827947..b2d38f29cde7 100644 --- a/svl/source/numbers/zformat.cxx +++ b/svl/source/numbers/zformat.cxx @@ -3052,7 +3052,7 @@ bool SvNumberformat::ImpGetFractionOutput(double fNumber, } sal_uInt16 SvNumberformat::ImpGetFractionOfSecondString( OUStringBuffer& rBuf, double fFractionOfSecond, - int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, sal_uInt16 nMinimumInputLineDecimals ) + int nFractionDecimals, bool bAddOneRoundingDecimal, sal_uInt16 nIx, sal_uInt16 nMinimumInputLineDecimals ) const { if (!nFractionDecimals) return 0; @@ -4327,7 +4327,7 @@ bool SvNumberformat::ImpGetDateTimeOutput(double fNumber, bool SvNumberformat::ImpGetLogicalOutput(double fNumber, sal_uInt16 nIx, - OUStringBuffer& sStr) + OUStringBuffer& sStr) const { bool bRes = false; const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info(); @@ -4350,7 +4350,7 @@ bool SvNumberformat::ImpGetLogicalOutput(double fNumber, bool SvNumberformat::ImpGetNumberOutput(double fNumber, sal_uInt16 nIx, - OUStringBuffer& sStr) + OUStringBuffer& sStr) const { bool bRes = false; bool bSign; @@ -4470,7 +4470,7 @@ bool SvNumberformat::ImpDecimalFill( OUStringBuffer& sStr, // number string sal_Int32 nDecPos, // decimals start sal_uInt16 j, // symbol index within format code sal_uInt16 nIx, // subformat index - bool bInteger) // is integer + bool bInteger) const // is integer { bool bRes = false; bool bFilled = false; // Was filled? @@ -4592,7 +4592,7 @@ bool SvNumberformat::ImpNumberFillWithThousands( OUStringBuffer& sBuff, // numb sal_uInt16 j, // symbol index within format code sal_uInt16 nIx, // subformat index sal_Int32 nDigCnt, // count of integer digits in format - bool bAddDecSep) // add decimal separator if necessary + bool bAddDecSep) const // add decimal separator if necessary { bool bRes = false; sal_Int32 nLeadingStringChars = 0; // inserted StringChars before number @@ -4752,7 +4752,7 @@ void SvNumberformat::ImpDigitFill(OUStringBuffer& sStr, // number string sal_Int32 & k, // position within string sal_uInt16 nIx, // subformat index sal_Int32 & nDigitCount, // count of integer digits from the right so far - utl::DigitGroupingIterator & rGrouping ) // current grouping + utl::DigitGroupingIterator & rGrouping ) const // current grouping { if (NumFor[nIx].Info().bThousand) // Only if grouping fill in separators { commit bb87f26fc0fcf2d15d180eb7bcd787c8c54e6023 Author: Caolán McNamara <caolan.mcnam...@collabora.com> AuthorDate: Sun May 5 16:39:36 2024 +0100 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:43 2024 +0200 cid#1596833 Uninitialized pointer field Change-Id: I1f05ef494e7e28bd105b7658072c33b2d274a803 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167159 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins (cherry picked from commit 66916b20818e4fc4a25d711b3860b4096e575a5c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167080 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> (cherry picked from commit a7587def8792dc811d9aa66a462d752130f575d5) diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index 81ef74d62f63..eee09889c226 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -1294,7 +1294,8 @@ namespace svgio::svgreader maDominantBaseline(DominantBaseline::Auto), maResolvingParent(33, 0), mbStrokeDasharraySet(false), - mbContextStroke(false) + mbContextStroke(false), + maContextStroke(nullptr) { } commit aabb4ddb320dc96a4f6d1c4ef64ace722ccc2d60 Author: Pierre <prrv...@gmail.com> AuthorDate: Sat Apr 13 19:19:50 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:30 2024 +0200 tdf#160375 Base displays and gives the full name of the table Change-Id: Icc8c6d85cc5a88461b7bd02487513e0e864bacef Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166093 Reviewed-by: Pierre Vacher <prrv...@gmail.com> Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> (cherry picked from commit eb045cc529f0e7b17e7e3bc913f2ab1748247966) diff --git a/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx b/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx index 2fb7c0b8213c..9651a89c9f09 100644 --- a/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx +++ b/dbaccess/source/ui/relationdesign/RTableConnectionData.cxx @@ -256,7 +256,8 @@ bool ORelationTableConnectionData::Update() xKey->setPropertyValue(PROPERTY_NAME,Any(sKeyName)); xKey->setPropertyValue(PROPERTY_TYPE,Any(KeyType::FOREIGN)); - xKey->setPropertyValue(PROPERTY_REFERENCEDTABLE,Any(getReferencedTable()->GetTableName())); + // get the full name of the tables to ensure uniqueness across catalogs and schema + xKey->setPropertyValue(PROPERTY_REFERENCEDTABLE,Any(getReferencedTable()->GetComposedName())); xKey->setPropertyValue(PROPERTY_UPDATERULE, Any(GetUpdateRules())); xKey->setPropertyValue(PROPERTY_DELETERULE, Any(GetDeleteRules())); } @@ -301,7 +302,7 @@ bool ORelationTableConnectionData::Update() { OUString sReferencedTable; xKey->getPropertyValue(PROPERTY_REFERENCEDTABLE) >>= sReferencedTable; - if ( sReferencedTable == getReferencedTable()->GetTableName() ) + if ( sReferencedTable == getReferencedTable()->GetComposedName() ) { xColSup.set(xKey,UNO_QUERY_THROW); try diff --git a/dbaccess/source/ui/relationdesign/RelationTableView.cxx b/dbaccess/source/ui/relationdesign/RelationTableView.cxx index 6c96d3952047..da82719b7a23 100644 --- a/dbaccess/source/ui/relationdesign/RelationTableView.cxx +++ b/dbaccess/source/ui/relationdesign/RelationTableView.cxx @@ -108,7 +108,8 @@ void ORelationTableView::ReSync() // it should be cleaned up, including its data in the document pTabWin->clearListBox(); pTabWin.disposeAndClear(); - arrInvalidTables.push_back(pData->GetTableName()); + // get the full name of the tables to ensure uniqueness across catalogs and schema + arrInvalidTables.push_back(pData->GetComposedName()); std::erase(rTabWinDataList, *aIter); continue; @@ -132,9 +133,9 @@ void ORelationTableView::ReSync() if ( !arrInvalidTables.empty() ) { // do the tables to the connection exist? - OUString strTabExistenceTest = pTabConnData->getReferencingTable()->GetTableName(); + OUString strTabExistenceTest = pTabConnData->getReferencingTable()->GetComposedName(); bool bInvalid = std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); - strTabExistenceTest = pTabConnData->getReferencedTable()->GetTableName(); + strTabExistenceTest = pTabConnData->getReferencedTable()->GetComposedName(); bInvalid = bInvalid || std::find(arrInvalidTables.begin(),arrInvalidTables.end(),strTabExistenceTest) != arrInvalidTables.end(); if (bInvalid) @@ -290,7 +291,8 @@ void ORelationTableView::AddTabWin(const OUString& _rComposedName, const OUStrin } // enter the new data structure into DocShell - TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName,rWinName )); + // show the table's full name as window name to ensure uniqueness across catalogs and schema + TTableWindowData::value_type pNewTabWinData(createTableWindowData( _rComposedName, rWinName, _rComposedName )); pNewTabWinData->ShowAll(false); // link new window into the window list commit 2e603b2bb0193c7b8918954584f0f0e059f28f28 Author: Julien Nabet <serval2...@yahoo.fr> AuthorDate: Sat May 4 10:18:15 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:20 2024 +0200 tdf#160924: SDK: typo SDK_HOME instead of OO_SDK_HOME for linux Change-Id: I8ec2bc31b19cc6b724a6f7ea3238dda8cf60d4b7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167111 Tested-by: Jenkins Reviewed-by: Julien Nabet <serval2...@yahoo.fr> (cherry picked from commit 6aa2e8fe2b0b59e2fe20191decb9bd6202dabcc9) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167073 Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com> Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakan...@libreoffice.org> (cherry picked from commit ee9f7d31348e917eb8ba5b007a6679e01ecdb37f) diff --git a/odk/docs/install.html b/odk/docs/install.html index aaafae6ce9c3..42e3b13cfb2f 100644 --- a/odk/docs/install.html +++ b/odk/docs/install.html @@ -459,7 +459,7 @@ <tr valign="top"> <td class="cell20">LD_LIBRARY_PATH</td> <td class="cell80">=<i>$OO_SDK_URE_LIB_DIR: - $SDK_HOME/linux/lib: + $OO_SDK_HOME/linux/lib: $LD_LIBRARY_PATH</i><br/> <p>The LD_LIBRARY_PATH will be set or will be extended by the office/URE library path, the commit 816d9fa689525666f49cb1b3b2407d44e3c4b2b5 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 23 05:25:34 2024 +0500 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:11 2024 +0200 Fix a thinko in 8a97f1ba8d9ccb65b2c89106de20666311d90c30 Change-Id: I07bb67e9384470269d1fd3df087acee377cce729 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166490 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/+/167052 (cherry picked from commit d1c31e3857b7f0c6b3fb72da0c967bfa2bdef015) diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 3e5708a99de6..9de634076960 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -188,7 +188,7 @@ void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontA } else { - mnFontScalingFixX = mnFontScalingFixY = 0; + mnFontScalingFixX = mnFontScalingFixY = 1.0; } } commit 8b98e21b1a061b3e47f5f5d51f743f7f2201ae4b Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Mon Apr 22 14:45:37 2024 +0500 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:12:01 2024 +0200 tdf#160773: handle 0-size font height Regression from commit cc3663bbaed4f65d64154e5f9abb51a5f622f710 (tdf#160702: improve text positioning, 2024-04-20), where I didn't know yet that this was possible :-) Change-Id: I1316db48b8acbacd077eeb4a8989c3dbf7e4a7b5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166425 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/+/167051 (cherry picked from commit 14c7b4249e822c218f912fcd3707226081363f7a) diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index afc0663aa4b0..3e5708a99de6 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -179,8 +179,17 @@ void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontA = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale); setFont(aFont); Size aFontSize = aFont.GetFontSize(); - mnFontScalingFixY = fFontScaleY / aFontSize.Height(); - mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); + if (aFontSize.Height()) + { + mnFontScalingFixY = fFontScaleY / aFontSize.Height(); + // aFontSize.Width() is 0 for uninformly scaled fonts: see getVclFontFromFontAttribute + mnFontScalingFixX + = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); + } + else + { + mnFontScalingFixX = mnFontScalingFixY = 0; + } } double TextLayouterDevice::getOverlineOffset() const commit 8173935b8491ff24831e849dbf6a7d872e680ddd Author: Xisco Fauli <xiscofa...@libreoffice.org> AuthorDate: Thu May 2 22:16:36 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:11:53 2024 +0200 tdf#155651: Add support for "context-stroke" Change-Id: Ib4f4a7b644d0d6c6b36e31b80fd7adc18999110d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166908 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> Tested-by: Jenkins (cherry picked from commit f4a868ce3b7e5fe6e708f2c795402d646e0746d5) diff --git a/svgio/inc/svgstyleattributes.hxx b/svgio/inc/svgstyleattributes.hxx index c5c095462f3d..61a3816e82cb 100644 --- a/svgio/inc/svgstyleattributes.hxx +++ b/svgio/inc/svgstyleattributes.hxx @@ -247,10 +247,15 @@ namespace svgio::svgreader // #121221# Defines if evtl. an empty array *is* set bool mbStrokeDasharraySet : 1; + // tdf#155651 Defines if 'context-stroke' is used in stroke + bool mbContextStroke : 1; + // tdf#94765 Check id references in gradient/pattern getters OUString maNodeFillURL; OUString maNodeStrokeURL; + const basegfx::BColor* maContextStroke; + /// internal helpers void add_fillGradient( const basegfx::B2DPolyPolygon& rPath, @@ -327,6 +332,9 @@ namespace svgio::svgreader /// stroke content const basegfx::BColor* getStroke() const; + /// context stroke content + const basegfx::BColor* getContextStroke() const; + /// stop color content const basegfx::BColor& getStopColor() const; diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index 69c6a10d23f4..dc900b1eee1e 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -685,6 +685,17 @@ CPPUNIT_TEST_FIXTURE(Test, testMarkerOrient) assertXPath(pDocument, "/primitive2D/transform/transform[2]"_ostr, "xy33"_ostr, "1"); } +CPPUNIT_TEST_FIXTURE(Test, testContextStroke) +{ + xmlDocUniquePtr pDocument = dumpAndParseSvg(u"/svgio/qa/cppunit/data/contextStroke.svg"); + + assertXPath(pDocument, "/primitive2D/transform/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[1]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[2]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[3]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); + assertXPath(pDocument, "/primitive2D/transform/transform[4]/polypolygonstroke/line"_ostr, "color"_ostr, "#ff0000"); +} + CPPUNIT_TEST_FIXTURE(Test, testMarkerInPresentation) { Primitive2DSequence aSequence = parseSvg(u"/svgio/qa/cppunit/data/markerInPresentation.svg"); diff --git a/svgio/qa/cppunit/data/contextStroke.svg b/svgio/qa/cppunit/data/contextStroke.svg new file mode 100644 index 000000000000..5a9b27d69c84 --- /dev/null +++ b/svgio/qa/cppunit/data/contextStroke.svg @@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> + <style> + path { + fill: none; + stroke-width: 4px; + marker: url(#diamond); + } + </style> + <path d="M 10,50 v -20 h 40 v -20" stroke="red"/> + + <marker id="diamond" markerWidth="12" markerHeight="12" refX="6" refY="6" markerUnits="userSpaceOnUse"> + <circle cx="6" cy="6" r="3" fill="white" stroke="context-stroke" stroke-width="2"/> + </marker> +</svg> diff --git a/svgio/source/svgreader/svgmarkernode.cxx b/svgio/source/svgreader/svgmarkernode.cxx index 083471b49c6b..2279920634a6 100644 --- a/svgio/source/svgreader/svgmarkernode.cxx +++ b/svgio/source/svgreader/svgmarkernode.cxx @@ -174,7 +174,7 @@ namespace svgio::svgreader const drawinglayer::primitive2d::Primitive2DContainer& SvgMarkerNode::getMarkerPrimitives() const { - if(aPrimitives.empty() && Display::None != getDisplay()) + if(Display::None != getDisplay()) { decomposeSvgNode(const_cast< SvgMarkerNode* >(this)->aPrimitives, true); } diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx index 50f72199e40b..81ef74d62f63 100644 --- a/svgio/source/svgreader/svgstyleattributes.cxx +++ b/svgio/source/svgreader/svgstyleattributes.cxx @@ -817,6 +817,11 @@ namespace svgio::svgreader rMarkerTransform.identity(); rClipRange.reset(); + // Set the current stroke to the marker before calling getMarkerPrimitives, + // which calls decomposeSvgNode to decompose the children of the marker. + // If any of the children uses 'stroke="context-stroke"', then it will use it + const_cast<SvgStyleAttributes*>(rMarker.getSvgStyleAttributes())->maContextStroke = getStroke(); + // get marker primitive representation rMarkerPrimitives = rMarker.getMarkerPrimitives(); @@ -1287,8 +1292,9 @@ namespace svgio::svgreader maBaselineShift(BaselineShift::Baseline), maBaselineShiftNumber(0), maDominantBaseline(DominantBaseline::Auto), - maResolvingParent(32, 0), - mbStrokeDasharraySet(false) + maResolvingParent(33, 0), + mbStrokeDasharraySet(false), + mbContextStroke(false) { } @@ -1353,7 +1359,11 @@ namespace svgio::svgreader OUString aURL; SvgNumber aOpacity; - if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity)) + if(o3tl::equalsIgnoreAsciiCase(o3tl::trim(aContent), u"context-stroke")) + { + mbContextStroke = true; + } + else if(readSvgPaint(aContent, aSvgPaint, aURL, aOpacity)) { maStroke = aSvgPaint; if(aOpacity.isSet()) @@ -1996,6 +2006,23 @@ namespace svgio::svgreader } } + const basegfx::BColor* SvgStyleAttributes::getContextStroke() const + { + if (SVGToken::Marker == mrOwner.getType()) + return maContextStroke; + + const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); + if (pSvgStyleAttributes && maResolvingParent[32] < nStyleDepthLimit) + { + ++maResolvingParent[32]; + auto ret = pSvgStyleAttributes->getContextStroke(); + --maResolvingParent[32]; + return ret; + } + + return nullptr; + } + bool SvgStyleAttributes::isClipPathContent() const { if (SVGToken::ClipPathNode == mrOwner.getType()) @@ -2109,6 +2136,10 @@ namespace svgio::svgreader return &maStroke.getBColor(); } } + else if (mbContextStroke) + { + return getContextStroke(); + } else if (maNodeStrokeURL.isEmpty()) { const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); commit acf30a32c7671278a2b6d3d20ac81726e56df254 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Apr 18 13:23:43 2024 +0500 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:11:45 2024 +0200 tdf#157103: fix SVG whitespace handling Previous code tried to hack some tricks to restore whitespaces after trimming them according to the xml:space attribute value. But it was wrong in multiple ways. 1. The collapsed space must stay in the block where its start was. When a block ended with a space, then trimming the space from it, and adding to a next block, can change the size of the space. 2. The shift of a line (e.g., specifying x and y values) doesn't end the logical line. A space before such a shift must be kept by the same rules, as if there weren't a shift. 3. A block with xml:space="preserve" is treated as if it consists of all non-whitespace characters, even if its leading or trailing characters are spaces. I.e., a trailing space in a block before, or a leading space in a block after, should be collapsed into a single space, not removed - even when the space-preserving block itself is made invisible. Change-Id: Ic778d1e9d6b9d0c342ea74ad78d44bb47bc8d708 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166239 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167050 Tested-by: Jenkins (cherry picked from commit 44b6b90080e7585e46250fb4076b210619e10bb3) diff --git a/svgio/inc/svgcharacternode.hxx b/svgio/inc/svgcharacternode.hxx index d81066af47a6..20c60d787cb5 100644 --- a/svgio/inc/svgcharacternode.hxx +++ b/svgio/inc/svgcharacternode.hxx @@ -38,11 +38,10 @@ namespace svgio::svgreader /// the string data OUString maText; - // keep a copy of string data before space handling - OUString maTextBeforeSpaceHandling; - SvgTspanNode* mpParentLine; + bool mbHadTrailingSpace = false; + /// local helpers rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> createSimpleTextPrimitive( SvgTextPosition& rSvgTextPosition, @@ -65,8 +64,7 @@ namespace svgio::svgreader virtual const SvgStyleAttributes* getSvgStyleAttributes() const override; void decomposeText(drawinglayer::primitive2d::Primitive2DContainer& rTarget, SvgTextPosition& rSvgTextPosition) const; - void whiteSpaceHandling(); - SvgCharacterNode* addGap(SvgCharacterNode* pPreviousCharacterNode); + SvgCharacterNode* whiteSpaceHandling(SvgCharacterNode* pPreviousCharacterNode); void concatenate(std::u16string_view rText); /// Text content diff --git a/svgio/qa/cppunit/SvgImportTest.cxx b/svgio/qa/cppunit/SvgImportTest.cxx index f6fb93634b8c..69c6a10d23f4 100644 --- a/svgio/qa/cppunit/SvgImportTest.cxx +++ b/svgio/qa/cppunit/SvgImportTest.cxx @@ -871,7 +871,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf85770) assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "height"_ostr, "11"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "familyname"_ostr, "Times New Roman"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "fontcolor"_ostr, "#000000"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, "Start"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, "Start "); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "height"_ostr, "11"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "familyname"_ostr, "Times New Roman"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "fontcolor"_ostr, "#000000"); @@ -916,17 +916,17 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf93583) CPPUNIT_ASSERT (pDocument); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "This is the"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "x"_ostr, "62"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "x"_ostr, "58"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "y"_ostr, "303"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "width"_ostr, "16"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "height"_ostr, "16"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, " first"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "x"_ostr, "128"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, " first "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "x"_ostr, "124"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "y"_ostr, "303"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "width"_ostr, "32"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "height"_ostr, "32"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "text"_ostr, " line"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "x"_ostr, "188"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "text"_ostr, "line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "x"_ostr, "192"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "y"_ostr, "303"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "width"_ostr, "16"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "height"_ostr, "16"); @@ -942,28 +942,28 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156616) CPPUNIT_ASSERT (pDocument); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "First"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "First "); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "x"_ostr, "114"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "y"_ostr, "103"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, " line"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "x"_ostr, "143"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, "line "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "x"_ostr, "147"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "y"_ostr, "103"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "text"_ostr, "Second line"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "x"_ostr, "114"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "y"_ostr, "122"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, "text"_ostr, "First"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, "x"_ostr, "86"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, "text"_ostr, "First "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, "x"_ostr, "84"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, "y"_ostr, "153"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "text"_ostr, " line"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "x"_ostr, "115"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "text"_ostr, "line "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "x"_ostr, "117"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "y"_ostr, "153"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, "text"_ostr, "Second line"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, "x"_ostr, "77"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, "y"_ostr, "172"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, "text"_ostr, "First"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, "x"_ostr, "59"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, "text"_ostr, "First "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, "x"_ostr, "55"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[7]"_ostr, "y"_ostr, "203"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, "text"_ostr, " line"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, "text"_ostr, "line "); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, "x"_ostr, "88"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[8]"_ostr, "y"_ostr, "203"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[9]"_ostr, "text"_ostr, "Second line"); @@ -1408,12 +1408,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156251) // Without the fix in place, this test would have failed with // - Expected: 'You are ' // - Actual : 'You are' - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "You are"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, " not"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "You are "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, "not"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[3]"_ostr, "text"_ostr, " a banana!"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[4]"_ostr, "text"_ostr, "You are"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "text"_ostr, " not"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, "text"_ostr, " a banana!"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[5]"_ostr, "text"_ostr, " not "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[6]"_ostr, "text"_ostr, "a banana!"); } CPPUNIT_TEST_FIXTURE(Test, testMaskText) @@ -1954,15 +1954,15 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf156837) assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "x"_ostr, "114"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "y"_ostr, "103"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "height"_ostr, "16"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "x"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "x"_ostr, "122"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[1]"_ostr, "text"_ostr, "x "); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "x"_ostr, "126"); // Without the fix in place, this test would have failed with // - Expected: 94 // - Actual : 103 assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "y"_ostr, "94"); assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "height"_ostr, "10"); - assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, " 3"); + assertXPath(pDocument, "/primitive2D/transform/textsimpleportion[2]"_ostr, "text"_ostr, "3"); } CPPUNIT_TEST_FIXTURE(Test, testTdf156271) diff --git a/svgio/source/svgreader/svgcharacternode.cxx b/svgio/source/svgreader/svgcharacternode.cxx index 7fdac9e92bc5..0aea1976c10f 100644 --- a/svgio/source/svgreader/svgcharacternode.cxx +++ b/svgio/source/svgreader/svgcharacternode.cxx @@ -486,53 +486,80 @@ namespace svgio::svgreader } } - void SvgCharacterNode::whiteSpaceHandling() + SvgCharacterNode* + SvgCharacterNode::whiteSpaceHandling(SvgCharacterNode* pPreviousCharacterNode) { bool bIsDefault(XmlSpace::Default == getXmlSpace()); // if xml:space="default" then remove all newline characters, otherwise convert them to space // convert tab to space too - maText = maTextBeforeSpaceHandling = maText.replaceAll(u" ", bIsDefault ? u"" : u" ").replaceAll(u" ", u" "); + maText = maText.replaceAll(u" ", bIsDefault ? u"" : u" ").replaceAll(u" ", u" "); - if(bIsDefault) + if (!bIsDefault) { - // strip of all leading and trailing spaces - // and consolidate contiguous space - maText = consolidateContiguousSpace(maText.trim()); - } - } + if (maText.isEmpty()) + { + // Ignore this empty node for the purpose of whitespace handling + return pPreviousCharacterNode; + } - SvgCharacterNode* SvgCharacterNode::addGap(SvgCharacterNode* pPreviousCharacterNode) - { - // maText may have lost all text. If that's the case, ignore as invalid character node - // Also ignore if maTextBeforeSpaceHandling just have spaces - if(!maText.isEmpty() && !o3tl::trim(maTextBeforeSpaceHandling).empty()) - { - if(pPreviousCharacterNode) + if (pPreviousCharacterNode && pPreviousCharacterNode->mbHadTrailingSpace) { - bool bAddGap(true); + // pPreviousCharacterNode->mbHadTrailingSpace implies its xml:space="default". + // Even if this xml:space="preserve" node is whitespace-only, the trailing space + // of the previous node is significant - restore it + pPreviousCharacterNode->maText += " "; + } + + return this; + } - // Do not add a gap if last node doesn't end with a space and - // current note doesn't start with a space - const sal_uInt32 nLastLength(pPreviousCharacterNode->maTextBeforeSpaceHandling.getLength()); - if(pPreviousCharacterNode->maTextBeforeSpaceHandling[nLastLength - 1] != ' ' && maTextBeforeSpaceHandling[0] != ' ') - bAddGap = false; + bool bHadLeadingSpace = maText.startsWith(" "); + mbHadTrailingSpace = maText.endsWith(" "); // Only set for xml:space="default" - // Do not add a gap if this node and last node are in different lines - if(pPreviousCharacterNode->mpParentLine != mpParentLine) - bAddGap = false; + // strip of all leading and trailing spaces + // and consolidate contiguous space + maText = consolidateContiguousSpace(maText.trim()); - // add in-between whitespace (single space) to the beginning of the current character node - if(bAddGap) + if (pPreviousCharacterNode) + { + if (pPreviousCharacterNode->mbHadTrailingSpace) + { + // pPreviousCharacterNode->mbHadTrailingSpace implies its xml:space="default". + // The previous node already has a pending trailing space. + if (maText.isEmpty()) { - maText = " " + maText; + // Leading spaces in this empty node are insignificant. + // Ignore this empty node for the purpose of whitespace handling + return pPreviousCharacterNode; } + // The previous node's trailing space is significant - restore it. Note that + // it is incorrect to insert a space in this node instead: the spaces in + // different nodes may have different size + pPreviousCharacterNode->maText += " "; + return this; } - // this becomes the previous character node - return this; + if (bHadLeadingSpace) + { + // This possibly whitespace-only xml:space="default" node goes after another + // node either having xml:space="default", but without a trailing space; or + // having xml:space="preserve" (in that case, it's irrelevant if that node had + // any trailing spaces). + if (!maText.isEmpty()) + { + // The leading whitespace in this node is significant - restore it + maText = " " + maText; + } + // The trailing whitespace in this node may or may not be + // significant (it will be significant, if there will be more nodes). Keep it as + // it is (even empty), but return this, to participate in whitespace handling + return this; + } } - return pPreviousCharacterNode; + // No previous node, or no leading/trailing space on the previous node's boundary: if + // this is whitespace-only, its whitespace is never significant + return maText.isEmpty() ? pPreviousCharacterNode : this; } void SvgCharacterNode::concatenate(std::u16string_view rText) diff --git a/svgio/source/svgreader/svgdocumenthandler.cxx b/svgio/source/svgreader/svgdocumenthandler.cxx index 8d2cc8849c55..5e6e0d404843 100644 --- a/svgio/source/svgreader/svgdocumenthandler.cxx +++ b/svgio/source/svgreader/svgdocumenthandler.cxx @@ -66,7 +66,46 @@ namespace svgio::svgreader namespace { - svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgNode const * pNode, svgio::svgreader::SvgTspanNode* pParentLine, svgio::svgreader::SvgCharacterNode* pLast) +using CharacterNodeHandlerFunc + = svgio::svgreader::SvgCharacterNode*(svgio::svgreader::SvgCharacterNode* pCharNode, + svgio::svgreader::SvgTspanNode* pParentLine, + svgio::svgreader::SvgCharacterNode* pLast); + // clean whitespace in text span + svgio::svgreader::SvgCharacterNode* whiteSpaceHandling(svgio::svgreader::SvgCharacterNode* pCharNode, + svgio::svgreader::SvgTspanNode* pParentLine, + svgio::svgreader::SvgCharacterNode* pLast) + { + pCharNode->setParentLine(pParentLine); + return pCharNode->whiteSpaceHandling(pLast); + } + + // set correct widths of text lines + svgio::svgreader::SvgCharacterNode* calcTextLineWidths(svgio::svgreader::SvgCharacterNode* pCharNode, + svgio::svgreader::SvgTspanNode* pParentLine, + svgio::svgreader::SvgCharacterNode* /*pLast*/) + { + if (const SvgStyleAttributes* pSvgStyleAttributes = pCharNode->getSvgStyleAttributes()) + { + const drawinglayer::attribute::FontAttribute aFontAttribute( + svgio::svgreader::SvgCharacterNode::getFontAttribute(*pSvgStyleAttributes)); + + double fFontWidth(pSvgStyleAttributes->getFontSizeNumber().solve(*pCharNode)); + double fFontHeight(fFontWidth); + + css::lang::Locale aLocale; + drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; + aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale); + double fTextWidth = aTextLayouterDevice.getTextWidth(pCharNode->getText(), 0.0, + pCharNode->getText().getLength()); + pParentLine->concatenateTextLineWidth(fTextWidth); + } + return nullptr; // no pLast handling + } + + svgio::svgreader::SvgCharacterNode* walkRecursive(svgio::svgreader::SvgNode const* pNode, + svgio::svgreader::SvgTspanNode* pParentLine, + svgio::svgreader::SvgCharacterNode* pLast, + CharacterNodeHandlerFunc* pHandlerFunc) { if(pNode) { @@ -83,34 +122,9 @@ namespace { case SVGToken::Character: { - // clean whitespace in text span svgio::svgreader::SvgCharacterNode* pCharNode = static_cast< svgio::svgreader::SvgCharacterNode* >(pCandidate); - pCharNode->setParentLine(pParentLine); - - pCharNode->whiteSpaceHandling(); - pLast = pCharNode->addGap(pLast); - - double fTextWidth(0.0); - - const SvgStyleAttributes* pSvgStyleAttributes = pCharNode->getSvgStyleAttributes(); - - if(pSvgStyleAttributes) - { - const drawinglayer::attribute::FontAttribute aFontAttribute( - svgio::svgreader::SvgCharacterNode::getFontAttribute(*pSvgStyleAttributes)); - - double fFontWidth(pSvgStyleAttributes->getFontSizeNumber().solve(*pCharNode)); - double fFontHeight(fFontWidth); - - css::lang::Locale aLocale; - - drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; - aTextLayouterDevice.setFontAttribute(aFontAttribute, fFontWidth, fFontHeight, aLocale); - fTextWidth = aTextLayouterDevice.getTextWidth(pCharNode->getText(), 0.0, pCharNode->getText().getLength()); - } - - pParentLine->concatenateTextLineWidth(fTextWidth); + pLast = pHandlerFunc(pCharNode, pParentLine, pLast); break; } case SVGToken::Tspan: @@ -121,15 +135,15 @@ namespace if(!pTspanNode->getX().empty() || !pTspanNode->getY().empty()) pParentLine = pTspanNode; - // recursively clean whitespaces in subhierarchy - pLast = whiteSpaceHandling(pCandidate, pParentLine, pLast); + // recursively handle subhierarchy + pLast = walkRecursive(pCandidate, pParentLine, pLast, pHandlerFunc); break; } case SVGToken::TextPath: case SVGToken::Tref: { - // recursively clean whitespaces in subhierarchy - pLast = whiteSpaceHandling(pCandidate, pParentLine, pLast); + // recursively handle subhierarchy + pLast = walkRecursive(pCandidate, pParentLine, pLast, pHandlerFunc); break; } default: @@ -516,7 +530,12 @@ namespace if(pTextNode) { // cleanup read strings - whiteSpaceHandling(pTextNode, static_cast< SvgTspanNode*>(pTextNode), nullptr); + // First pass: handle whitespace. This works in a way that handling a following + // node may append a space to a previous node; so correct line width calculation + // may only happen after this pass finishes + walkRecursive(pTextNode, static_cast<SvgTspanNode*>(pTextNode), nullptr, whiteSpaceHandling); + // Second pass: calculate line widths + walkRecursive(pTextNode, static_cast<SvgTspanNode*>(pTextNode), nullptr, calcTextLineWidths); } } commit 063a24044ee3e6b225147f619d1f77b8270499fa Author: Julien Nabet <serval2...@yahoo.fr> AuthorDate: Fri May 3 08:04:53 2024 +0200 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:11:36 2024 +0200 tdf#160916: typo "Checbox" Change-Id: Ia06bc947cd1788850251b1386977ef0229dddd8a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167030 Reviewed-by: Julien Nabet <serval2...@yahoo.fr> Tested-by: Jenkins (cherry picked from commit 68008d9f0176c43ecc768af8e3539227640d1519) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166905 Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com> Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org> Tested-by: Julien Nabet <serval2...@yahoo.fr> (cherry picked from commit f1b1e61ef56b85fd56f39854d2edb52f3c2d8b82) diff --git a/extras/source/tipoftheday/formdocuments.svg b/extras/source/tipoftheday/formdocuments.svg index b6ad08cab3d7..a3d752292fa5 100644 --- a/extras/source/tipoftheday/formdocuments.svg +++ b/extras/source/tipoftheday/formdocuments.svg @@ -1 +1 @@ -<svg height="150" viewBox="0 0 39.687499 39.6875" width="150" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><filter id="a" color-interpolation-filters="sRGB" height="1.13824" width="1.136293" x="-.068146" y="-.06912"><feGaussianBlur stdDeviation="1.0668"/></filter><g stroke-width=".264583"><path d="m1.3229163 1.852083 37.5708337-.0000022v37.0416692l-37.5708337.000002z" fill="#48484a" filter="url(#a)" opacity=".557352" stroke-opacity=".501961"/><path d="m1.5875003 2.116667h37.0416677v35.983334h-37.0416677z" fill="#f2f2f7" stroke-opacity=".501961"/><text stroke-linecap="round" stroke-linejoin="round" x="34.924999" y="2.645833"><tspan stroke-width=".264583" x="34.924999" y="2.645833"/></text><path d="m1.5875 2.1166666h37.041668v8.9958334h-37.041668z" fill="#d1d1d6" stroke-linecap="round" stroke-linejoin="round"/><text fill="#48484a" font-family="Inter" font-size="3.52778" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="7.878621"><tspan fi ll="#48484a" font-family="Inter" font-size="3.52778" font-weight="bold" stroke-width=".264583" x="13.448908" y="7.878621">PDF Form</tspan></text><g transform="translate(.071347 16.933337)"><path d="m6.543236 5.0270833c-.2931584 0-.5291667.2360083-.5291667.5291666v2.9104167c0 .2931583.2360083.5291667.5291667.5291667h2.9104166c.2931583 0 .5291667-.2360084.5291667-.5291667v-2.9104167c0-.2931583-.2360084-.5291666-.5291667-.5291666zm.1322916.2645833h2.6458333c.2198688 0 .396875.1770063.396875.396875v2.6458333c0 .2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z" fill="#44b1e9"/><path d="m6.6755276 5.2916666h2.6458333c.2198688 0 .396875.1770063.396875.396875v2.6458333c0 .2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z" fill="#93cee9"/><path d="m6.543236 6.8791666v.396875l1.0583333 1.0583333 1 .8520833-1.8520833v-.396875h-.4578194l-1.3942639 1.3229167-.5291667-.5291667z" fill="#232629"/></g><g transform="translate(6.085417 28.839591)"><path d="m1.984375 0a1.984375 1.984375 0 0 0 -1.984375 1.984375 1.984375 1.984375 0 0 0 1.984375 1.984375 1.984375 1.984375 0 0 0 1.984375-1.984375 1.984375 1.984375 0 0 0 -1.984375-1.984375zm0 .26458333a1.7197916 1.7197916 0 0 1 1.7197916 1.71979167 1.7197916 1.7197916 0 0 1 -1.7197916 1.7197916 1.7197916 1.7197916 0 0 1 -1.71979167-1.7197916 1.7197916 1.7197916 0 0 1 1.71979167-1.71979167z" fill="#44b1e9"/><path d="m3.7041666 1.984375a1.7197916 1.7197916 0 0 1 -1.7197916 1.7197916 1.7197916 1.7197916 0 0 1 -1.71979167-1.7197916 1.7197916 1.7197916 0 0 1 1.71979167-1.71979167 1.7197916 1.7197916 0 0 1 1.7197916 1.71979167z" fill="#93cee9"/><path d="m2.778125 1.984375a.79374999.79374999 0 0 1 -.79375.79375.79374999.79374999 0 0 1 -.79375-.79375.79374999.79374999 0 0 1 .79375-.79375.79374999.79374999 0 0 1 .79375.79375z" fill="#232629"/></g>< g fill="#48484a"><text font-family="Inter" font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="25.225746"><tspan fill="#48484a" font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" y="25.225746">Checbox</tspan></text><text font-family="Inter" font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="31.994297"><tspan fill="#48484a" font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" y="31.994297">Radio Button</tspan></text><text font-family="Inter" font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="18.346573"><tspan fill="#48484a" font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" y="18.346573">Text Box</tspan></text></g><path d="m7.7333779 14.948958-1.0231933 2.901115-.037724.122473-.4547527 1.209745h.511597l.5017781-1.342037h1.677417l.5017781 1.342037h.5115967l-.4547526-1.209745-.0377238-.122473-1.0231934-2.901115h-.0661459-.5405 353zm.3410644.586011.6728273 1.918229h-1.3549561z" fill="#232629"/></g><g transform="translate(.529167)"><path d="m5.0270833 3.7041667v5.8208332h4.7624999v-3.96875l-1.8520833-1.8520832zm.2645833.2645833h2.38125v1.8520833h1.8520833v3.4395833h-4.2333333z" fill="#48484a" stroke-width=".264583"/><path d="m5.8208333 8.4666666c1.3829607-1.1563781 1.2720396-2.0342018 1.2271086-2.92433-.198148 1.4292522.5394675 1.9405571 1.6971971 2.0397454-.8730557-.2752884-1.7982518-.2583058-2.9243057.8845846z" fill="none" stroke="#ed3d3b" stroke-linecap="round" stroke-linejoin="round" stroke-width=".250965"/></g></svg> \ No newline at end of file +<svg height="150" viewBox="0 0 39.687499 39.6875" width="150" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><filter id="a" color-interpolation-filters="sRGB" height="1.13824" width="1.136293" x="-.068146" y="-.06912"><feGaussianBlur stdDeviation="1.0668"/></filter><g stroke-width=".264583"><path d="m1.3229163 1.852083 37.5708337-.0000022v37.0416692l-37.5708337.000002z" fill="#48484a" filter="url(#a)" opacity=".557352" stroke-opacity=".501961"/><path d="m1.5875003 2.116667h37.0416677v35.983334h-37.0416677z" fill="#f2f2f7" stroke-opacity=".501961"/><text stroke-linecap="round" stroke-linejoin="round" x="34.924999" y="2.645833"><tspan stroke-width=".264583" x="34.924999" y="2.645833"/></text><path d="m1.5875 2.1166666h37.041668v8.9958334h-37.041668z" fill="#d1d1d6" stroke-linecap="round" stroke-linejoin="round"/><text fill="#48484a" font-family="Inter" font-size="3.52778" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="7.878621"><tspan fi ll="#48484a" font-family="Inter" font-size="3.52778" font-weight="bold" stroke-width=".264583" x="13.448908" y="7.878621">PDF Form</tspan></text><g transform="translate(.071347 16.933337)"><path d="m6.543236 5.0270833c-.2931584 0-.5291667.2360083-.5291667.5291666v2.9104167c0 .2931583.2360083.5291667.5291667.5291667h2.9104166c.2931583 0 .5291667-.2360084.5291667-.5291667v-2.9104167c0-.2931583-.2360084-.5291666-.5291667-.5291666zm.1322916.2645833h2.6458333c.2198688 0 .396875.1770063.396875.396875v2.6458333c0 .2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z" fill="#44b1e9"/><path d="m6.6755276 5.2916666h2.6458333c.2198688 0 .396875.1770063.396875.396875v2.6458333c0 .2198688-.1770062.396875-.396875.396875h-2.6458333c-.2198687 0-.396875-.1770062-.396875-.396875v-2.6458333c0-.2198687.1770063-.396875.396875-.396875z" fill="#93cee9"/><path d="m6.543236 6.8791666v.396875l1.0583333 1.0583333 1 .8520833-1.8520833v-.396875h-.4578194l-1.3942639 1.3229167-.5291667-.5291667z" fill="#232629"/></g><g transform="translate(6.085417 28.839591)"><path d="m1.984375 0a1.984375 1.984375 0 0 0 -1.984375 1.984375 1.984375 1.984375 0 0 0 1.984375 1.984375 1.984375 1.984375 0 0 0 1.984375-1.984375 1.984375 1.984375 0 0 0 -1.984375-1.984375zm0 .26458333a1.7197916 1.7197916 0 0 1 1.7197916 1.71979167 1.7197916 1.7197916 0 0 1 -1.7197916 1.7197916 1.7197916 1.7197916 0 0 1 -1.71979167-1.7197916 1.7197916 1.7197916 0 0 1 1.71979167-1.71979167z" fill="#44b1e9"/><path d="m3.7041666 1.984375a1.7197916 1.7197916 0 0 1 -1.7197916 1.7197916 1.7197916 1.7197916 0 0 1 -1.71979167-1.7197916 1.7197916 1.7197916 0 0 1 1.71979167-1.71979167 1.7197916 1.7197916 0 0 1 1.7197916 1.71979167z" fill="#93cee9"/><path d="m2.778125 1.984375a.79374999.79374999 0 0 1 -.79375.79375.79374999.79374999 0 0 1 -.79375-.79375.79374999.79374999 0 0 1 .79375-.79375.79374999.79374999 0 0 1 .79375.79375z" fill="#232629"/></g>< g fill="#48484a"><text font-family="Inter" font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="25.225746"><tspan fill="#48484a" font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" y="25.225746">Checkbox</tspan></text><text font-family="Inter" font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="31.994297"><tspan fill="#48484a" font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" y="31.994297">Radio Button</tspan></text><text font-family="Inter" font-size="3.175" stroke-linecap="round" stroke-linejoin="round" x="13.448908" y="18.346573"><tspan fill="#48484a" font-family="Inter" font-size="3.175" stroke-width=".264583" x="13.448908" y="18.346573">Text Box</tspan></text></g><path d="m7.7333779 14.948958-1.0231933 2.901115-.037724.122473-.4547527 1.209745h.511597l.5017781-1.342037h1.677417l.5017781 1.342037h.5115967l-.4547526-1.209745-.0377238-.122473-1.0231934-2.901115h-.0661459-.540 5353zm.3410644.586011.6728273 1.918229h-1.3549561z" fill="#232629"/></g><g transform="translate(.529167)"><path d="m5.0270833 3.7041667v5.8208332h4.7624999v-3.96875l-1.8520833-1.8520832zm.2645833.2645833h2.38125v1.8520833h1.8520833v3.4395833h-4.2333333z" fill="#48484a" stroke-width=".264583"/><path d="m5.8208333 8.4666666c1.3829607-1.1563781 1.2720396-2.0342018 1.2271086-2.92433-.198148 1.4292522.5394675 1.9405571 1.6971971 2.0397454-.8730557-.2752884-1.7982518-.2583058-2.9243057.8845846z" fill="none" stroke="#ed3d3b" stroke-linecap="round" stroke-linejoin="round" stroke-width=".250965"/></g></svg> commit 0100a9bc2c517acb7204b09714777339798f18db Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Tue Apr 16 10:48:06 2024 +0500 Commit: Aron Budea <aron.bu...@collabora.com> CommitDate: Wed May 8 08:11:28 2024 +0200 tdf#160702: improve text positioning Opening an SVG with text in different elements (e.g., tspans) in the same text element performs calculations to position the parts properly (i.e., the next part will start where the previous part ended, unless the position in overridden explicitly). These calculations require to know the text widths. The first problem leas here: the text width was calculated for a typically small text size (numerically equal to the pixel size defined in the SVG), but these calculations aren't truly linear, because font rendering may change depending on font height. Additionally, the rounding gives much higher error in smaller sizes than in larger. There was already a workaround for a similar problem in ViewRedirector::createRedirectedPrimitive2DSequence, where a large font (with 100 times greater height) was used to increase correctness. This was also used here, with the same large height (50000) used as a reference. Then, at the time of wrawing the text at different zoom levels, the code in VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D creates a font of a calculated size, and uses it to output the text. But the font is always created with an integral height, which means, that for a wanted height of 2.5 (in a zoomed out view), the really used height will be 3, which is 20% larger; or for wanted height of 2.4, the actual height will be 2 (20% smaller). This resulted in odd jumps of the text widths, when the text may overlap the following part, or conversely, create a big gap before the next gap. To try to mitigate that, the function now takes the difference between the wanted and the actual font size into account, and adjusts the MapMode accordingly. This doesn't fix the jumping completely (e.g., because of the mentioned special handling of small font sizes in the fonts thenselves, like hinting), but still makes the calculations much more stable, decreasing the amount of jumping. Similar changes are made in TextLayouterDevice. Use of the functions that return text size as a double, not rounded value, should additionally help improving stability. Change-Id: I455845d8ca43ee9c06a0fc980947f35d8a25797a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/166238 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/+/166468 (cherry picked from commit 5a25899a9c5c0c4e6fb92ca355ea1e24cec3a747) diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 5145d84ed2b6..afc0663aa4b0 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -22,6 +22,8 @@ #include <algorithm> #include <com/sun/star/uno/XComponentContext.hpp> + +#include <basegfx/matrix/b2dhommatrixtools.hxx> #include <drawinglayer/attribute/fontattribute.hxx> #include <drawinglayer/primitive2d/textlayoutdevice.hxx> #include <comphelper/processfactory.hxx> @@ -162,56 +164,69 @@ TextLayouterDevice::TextLayouterDevice() TextLayouterDevice::~TextLayouterDevice() COVERITY_NOEXCEPT_FALSE { releaseGlobalVirtualDevice(); } -void TextLayouterDevice::setFont(const vcl::Font& rFont) { mrDevice.SetFont(rFont); } +void TextLayouterDevice::setFont(const vcl::Font& rFont) +{ + mrDevice.SetFont(rFont); + mnFontScalingFixX = 1.0; + mnFontScalingFixY = 1.0; +} void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontAttribute, double fFontScaleX, double fFontScaleY, const css::lang::Locale& rLocale) { - setFont(getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale)); + vcl::Font aFont + = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale); + setFont(aFont); + Size aFontSize = aFont.GetFontSize(); + mnFontScalingFixY = fFontScaleY / aFontSize.Height(); + mnFontScalingFixX = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height()); } double TextLayouterDevice::getOverlineOffset() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = (rMetric.GetInternalLeading() / 2.0) - rMetric.GetAscent(); - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getUnderlineOffset() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = rMetric.GetDescent() / 2.0; - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getStrikeoutOffset() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = (rMetric.GetAscent() - rMetric.GetInternalLeading()) / 3.0; - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getOverlineHeight() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = rMetric.GetInternalLeading() / 2.5; - return fRet; + return fRet * mnFontScalingFixY; } double TextLayouterDevice::getUnderlineHeight() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); double fRet = rMetric.GetDescent() / 4.0; - return fRet; + return fRet * mnFontScalingFixY; } -double TextLayouterDevice::getTextHeight() const { return mrDevice.GetTextHeight(); } +double TextLayouterDevice::getTextHeight() const +{ + return mrDevice.GetTextHeight() * mnFontScalingFixY; +} double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 nIndex, sal_uInt32 nLength) const { - return mrDevice.GetTextWidth(rText, nIndex, nLength); + return mrDevice.GetTextWidth(rText, nIndex, nLength) * mnFontScalingFixX; } void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, @@ -245,6 +260,13 @@ void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPoly { mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength); } + if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0) + || !rtl_math_approxEqual(mnFontScalingFixX, 1.0)) + { + auto scale = basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY); + for (auto& poly : rB2DPolyPolyVector) + poly.transform(scale); + } } basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sal_uInt32 nIndex, @@ -262,6 +284,12 @@ basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sa { basegfx::B2DRange aRect; mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength); + if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0) + || !rtl_math_approxEqual(mnFontScalingFixX, 1.0)) + { + aRect.transform( + basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY)); + } return aRect; } @@ -271,13 +299,13 @@ basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sa double TextLayouterDevice::getFontAscent() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); - return rMetric.GetAscent(); -e ... etc. - the rest is truncated