desktop/source/lib/init.cxx | 24 +++++++++++++++++++++--- include/vcl/ITiledRenderable.hxx | 9 +++++++++ sc/inc/docuno.hxx | 3 +++ sc/inc/scextopt.hxx | 1 + sc/qa/unit/tiledrendering/tiledrendering.cxx | 18 ++++++++++++++++++ sc/source/filter/excel/xeview.cxx | 4 +++- sc/source/ui/inc/viewdata.hxx | 5 +++++ sc/source/ui/unoobj/docuno.cxx | 13 +++++++++++++ sc/source/ui/view/viewdata.cxx | 11 +++++++++++ xmloff/source/core/xmlexp.cxx | 7 +++++++ 10 files changed, 91 insertions(+), 4 deletions(-)
New commits: commit feb4ecf424cbe71290c8b39522a4287b5e807f3b Author: Mohit Marathe <[email protected]> AuthorDate: Thu Jul 31 19:48:12 2025 +0530 Commit: Mohit Marathe <[email protected]> CommitDate: Tue Oct 21 08:17:27 2025 +0200 cool#4250 LOK calc export: use LOK Zoom via ScViewData Justin Luth's comment on the original patch (to which I made some minor tweaks to adapt to the new simplified API): "The zoom values set in the view properties by LibreOfficeKit are technical zoom levels that depend on the current screen DPI. They do not reflect the logical zoom level that the user sees. This has been especially problematic for high DPI screens, where the technical-zoom-level is completely different from the human-zoom-level - and thus a weird value is exported. Instead, export the zoom value that LOK presents to the human. Since LOK doc_setClientZoom always calls setZoom for bAll sheets, it is sufficient to only have a single export zoom variable. COOL doesn't have a "View - Page break" view, so PageZoomValue is irrelevant. Of course, even in desktop mode it seems irrelevant to me... I'm rather worried about the "IsLOKExport" flag interferring with normal, synchronous operations during a background/download ODT save. Those WriteUserDataSequence are not at all limited to file-save operations. They just fill in property values for 'whatever' wants to capture the view settings. So if some other process runs in parallel with the save, then it will get the export zoom values, rather than the operational zoom values it was expecting. But I don't see any way around it since xmloff just dumps properties as the way that it saves an ODS. make CppunitTest_sc_tiledrendering \ CPPUNIT_TEST_NAME=testCellInvalidationDocWithExistingZoom" Signed-off-by: Mohit Marathe <[email protected]> Co-authored-by: Justin Luth <[email protected]> Change-Id: I54282e4d28dbe489ca0ea7c080036391faa4704c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188674 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> (cherry picked from commit 22dbeb3505af9cf7e7d4a07412616652ade67dcd) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192764 Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index c093efa36060..3320d08140fd 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -3914,7 +3914,6 @@ static int doc_saveAs(LibreOfficeKitDocument* pThis, const char* sUrl, const cha aSaveMediaDescriptor[MediaDescriptor::PROP_INTERACTIONHANDLER] <<= xInteraction; } - if (bTakeOwnership) xStorable->storeAsURL(aURL, aSaveMediaDescriptor.getAsConstPropertyValueList()); else @@ -5871,9 +5870,28 @@ static bool doc_renderNextSlideLayer( return bDone; } -static void doc_setViewOption(LibreOfficeKitDocument* /*pDoc*/, const char* /*pOption*/, const char* /*pValue*/) +static void doc_setViewOption(LibreOfficeKitDocument* pThis, const char* pOption, const char* pValue) { - // placeholder for now + comphelper::ProfileZone aZone("doc_setViewOption"); + + ITiledRenderable* pDoc = getTiledRenderable(pThis); + if (!pDoc) + { + SetLastExceptionMsg(u"Document doesn't support tiled rendering"_ustr); + return; + } + + SolarMutexGuard aGuard; + SetLastExceptionMsg(); + + const OUString sOption = getUString(pOption); + if (sOption == "zoom") + { + const int nZoom = getUString(pValue).toInt32(); + + if (nZoom) + pDoc->setExportZoom(nZoom); + } } static bool getFromTransferable( diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx index 1e3502a781af..f93e831a38ea 100644 --- a/include/vcl/ITiledRenderable.hxx +++ b/include/vcl/ITiledRenderable.hxx @@ -279,6 +279,15 @@ public: int /*nTileTwipHeight*/) {} + /** + * Provide the zoom level that will used during save/export + * + * @param nExportZoom - the zoom level as a percent + */ + virtual void setExportZoom(int /*nExportZoom*/) + { + } + /// @see lok::Document::setClientVisibleArea(). virtual void setClientVisibleArea(const tools::Rectangle& /*rRectangle*/) { diff --git a/sc/inc/docuno.hxx b/sc/inc/docuno.hxx index 3f47b0099fe0..6a1ef1d2a6ac 100644 --- a/sc/inc/docuno.hxx +++ b/sc/inc/docuno.hxx @@ -369,6 +369,9 @@ public: /// @see vcl::ITiledRenderable::setClientZoom(). virtual void setClientZoom(int nTilePixelWidth, int nTilePixelHeight, int nTileTwipWidth, int nTileTwipHeight) override; + /// @see vcl::ITiledRenderable::setExportZoom(). + virtual void setExportZoom(int nExportZoom) override; + /// @see vcl::ITiledRenderable::setOutlineState(). virtual void setOutlineState(bool bColumn, int nLevel, int nIndex, bool bHidden) override; diff --git a/sc/inc/scextopt.hxx b/sc/inc/scextopt.hxx index 843dfa6ebab0..4a71fdd7dd30 100644 --- a/sc/inc/scextopt.hxx +++ b/sc/inc/scextopt.hxx @@ -57,6 +57,7 @@ struct ScExtTabSettings Color maGridColor; ///< Grid color. tools::Long mnNormalZoom; ///< Zoom in percent for normal view. tools::Long mnPageZoom; ///< Zoom in percent for pagebreak preview. + std::optional<sal_uInt16> moExportZoom; ///< Zoom in percent - use when NormalZoom isn't accurate bool mbSelected; ///< true = Sheet is selected. bool mbFrozenPanes; ///< true = Frozen panes; false = Normal splits. bool mbPageMode; ///< true = Pagebreak mode; false = Normal view mode. diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index f4f0d15bcc6a..fc121e347220 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -18,6 +18,7 @@ #include <comphelper/processfactory.hxx> #include <comphelper/propertysequence.hxx> #include <comphelper/servicehelper.hxx> +#include <comphelper/SetFlagContextHelper.hxx> #include <sfx2/dispatch.hxx> #include <sfx2/viewfrm.hxx> #include <svl/stritem.hxx> @@ -3132,6 +3133,23 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testCellInvalidationDocWithExistingZo CPPUNIT_ASSERT_RECTANGLE_EQUAL_WITH_TOLERANCE(aView2.m_aInvalidations[0], aView1.m_aInvalidations[0], 50); + // cool#4250: zoom values + pModelObj->setExportZoom(150); + + { + uno::ContextLayer aLayer(comphelper::NewFlagContext(u"IsLOKExport"_ustr)); + save(u"calc8"_ustr); // .ODS + } + xmlDocUniquePtr pSettingsXml = parseExport(u"settings.xml"_ustr); + // Multi-user export: don't save every user's view into the exported file + // assertXPath(pSettingsXml, "//config:config-item[@config:name='ViewId']", 1); + // Use view's logic (not technical) zoom level for export + assertXPathContent(pSettingsXml, "//config:config-item[@config:name='ZoomValue'][1]", u"150"); + + save(u"Calc Office Open XML"_ustr); // .XLSX + xmlDocUniquePtr pSheet1Xml = parseExport(u"xl/worksheets/sheet1.xml"_ustr); + // Use view's logic (not technical) zoom level for export + assertXPath(pSheet1Xml, "//x:sheetViews/x:sheetView", "zoomScale", u"150"); } CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testInputHandlerSyncedZoom) diff --git a/sc/source/filter/excel/xeview.cxx b/sc/source/filter/excel/xeview.cxx index c5760fafcdb7..50b6d57bfe02 100644 --- a/sc/source/filter/excel/xeview.cxx +++ b/sc/source/filter/excel/xeview.cxx @@ -383,7 +383,9 @@ XclExpTabViewSettings::XclExpTabViewSettings( const XclExpRoot& rRoot, SCTAB nSc // view mode and zoom maData.mbPageMode = (GetBiff() == EXC_BIFF8) && rTabSett.mbPageMode; - maData.mnNormalZoom = lclGetXclZoom( rTabSett.mnNormalZoom, EXC_WIN2_NORMALZOOM_DEF ); + const tools::Long nNormalZoom + = rTabSett.moExportZoom ? *rTabSett.moExportZoom : rTabSett.mnNormalZoom; + maData.mnNormalZoom = lclGetXclZoom(nNormalZoom, EXC_WIN2_NORMALZOOM_DEF); maData.mnPageZoom = lclGetXclZoom( rTabSett.mnPageZoom, EXC_WIN2_PAGEZOOM_DEF ); maData.mnCurrentZoom = maData.mbPageMode ? maData.mnPageZoom : maData.mnNormalZoom; } diff --git a/sc/source/ui/inc/viewdata.hxx b/sc/source/ui/inc/viewdata.hxx index 9d848697172c..e1361efdd40b 100644 --- a/sc/source/ui/inc/viewdata.hxx +++ b/sc/source/ui/inc/viewdata.hxx @@ -296,6 +296,8 @@ private: Fraction aDefZoomY; Fraction aDefPageZoomX; // zoom in page break preview mode Fraction aDefPageZoomY; + // If the actual zoom values are for implemention-only purposes, then provide a value for export + std::optional<sal_uInt16> oExportZoom; // used for all sheets ScRefType eRefType; @@ -489,6 +491,9 @@ public: const Fraction& GetZoomX() const { return bPagebreak ? pThisTab->aPageZoomX : pThisTab->aZoomX; } const Fraction& GetZoomY() const { return bPagebreak ? pThisTab->aPageZoomY : pThisTab->aZoomY; } + void SetExportZoom(sal_uInt16 nExportZoom) { oExportZoom = nExportZoom; } + const std::optional<sal_uInt16>& GetExportZoom() const { return oExportZoom; } + void SetShowGrid( bool bShow ); bool GetShowGrid() const { return pThisTab->bShowGrid; } diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index b78e8c581527..8f7de5a1c990 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -1146,6 +1146,19 @@ void ScModelObj::setClientZoom(int nTilePixelWidth_, int nTilePixelHeight_, int pDrawView->resetGridOffsetsForAllSdrPageViews(); } +void ScModelObj::setExportZoom(int nExportZoom) +{ + ScViewData* pViewData = ScDocShell::GetViewData(); + if (!pViewData) + return; + + if (pViewData->GetZoomType() != SvxZoomType::PERCENT) + return; + + assert(nExportZoom > 0 && nExportZoom <= SAL_MAX_UINT16); + pViewData->SetExportZoom(nExportZoom); +} + void ScModelObj::getRowColumnHeaders(const tools::Rectangle& rRectangle, tools::JsonWriter& rJsonWriter) { ScViewData* pViewData = ScDocShell::GetViewData(); diff --git a/sc/source/ui/view/viewdata.cxx b/sc/source/ui/view/viewdata.cxx index bd0255c884a4..78c609f84f47 100644 --- a/sc/source/ui/view/viewdata.cxx +++ b/sc/source/ui/view/viewdata.cxx @@ -65,6 +65,7 @@ #include <comphelper/flagguard.hxx> #include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> +#include <comphelper/SetFlagContextHelper.hxx> #include <comphelper/string.hxx> #include <vcl/uitest/logger.hxx> @@ -606,6 +607,11 @@ void ScViewDataTable::WriteUserDataSequence(uno::Sequence <beans::PropertyValue> sal_Int32 nPageZoomValue = tools::Long(aPageZoomY * 100); pSettings[SC_TABLE_ZOOM_TYPE].Name = SC_ZOOMTYPE; pSettings[SC_TABLE_ZOOM_TYPE].Value <<= sal_Int16(eZoomType); + + const std::optional<sal_uInt16>& oExportZoom = rViewData.GetExportZoom(); + if (oExportZoom && comphelper::IsContextFlagActive(u"IsLOKExport"_ustr)) + nZoomValue = *oExportZoom; + pSettings[SC_TABLE_ZOOM_VALUE].Name = SC_ZOOMVALUE; pSettings[SC_TABLE_ZOOM_VALUE].Value <<= nZoomValue; pSettings[SC_TABLE_PAGE_VIEW_ZOOM_VALUE].Name = SC_PAGEVIEWZOOMVALUE; @@ -3643,6 +3649,7 @@ void ScViewData::WriteExtOptions( ScExtDocOptions& rDocOpt ) const rTabSett.mbPageMode = bPagebreak; rTabSett.mnNormalZoom = static_cast< tools::Long >( pViewTab->aZoomY * Fraction( 100.0 ) ); rTabSett.mnPageZoom = static_cast< tools::Long >( pViewTab->aPageZoomY * Fraction( 100.0 ) ); + rTabSett.moExportZoom = GetExportZoom(); } } } @@ -3857,6 +3864,10 @@ void ScViewData::WriteUserDataSequence(uno::Sequence <beans::PropertyValue>& rSe sal_Int32 nPageZoomValue = tools::Long(pThisTab->aPageZoomY * 100); pSettings[SC_ZOOM_TYPE].Name = SC_ZOOMTYPE; pSettings[SC_ZOOM_TYPE].Value <<= sal_Int16(pThisTab->eZoomType); + + if (oExportZoom && comphelper::IsContextFlagActive(u"IsLOKExport"_ustr)) + nZoomValue = *oExportZoom; + pSettings[SC_ZOOM_VALUE].Name = SC_ZOOMVALUE; pSettings[SC_ZOOM_VALUE].Value <<= nZoomValue; pSettings[SC_PAGE_VIEW_ZOOM_VALUE].Name = SC_PAGEVIEWZOOMVALUE; diff --git a/xmloff/source/core/xmlexp.cxx b/xmloff/source/core/xmlexp.cxx index a6a1fb65aef0..633124bb1486 100644 --- a/xmloff/source/core/xmlexp.cxx +++ b/xmloff/source/core/xmlexp.cxx @@ -46,6 +46,7 @@ #include <comphelper/processfactory.hxx> #include <comphelper/propertysetinfo.hxx> #include <comphelper/propertyvalue.hxx> +#include <comphelper/lok.hxx> #include <xmloff/namespacemap.hxx> #include <xmloff/xmluconv.hxx> #include <xmloff/xmlnamespace.hxx> @@ -1819,6 +1820,12 @@ void SvXMLExport::GetViewSettingsAndViews(uno::Sequence<beans::PropertyValue>& r if(!xViewDataSupplier.is()) return; + std::optional<css::uno::ContextLayer> oLayer; + if (comphelper::LibreOfficeKit::isActive()) + { + oLayer.emplace(comphelper::NewFlagContext(u"IsLOKExport"_ustr)); + } + uno::Reference<container::XIndexAccess> xIndexAccess; xViewDataSupplier->setViewData( xIndexAccess ); // make sure we get a newly created sequence {
