diff options
Diffstat (limited to 'drawinglayer/source/geometry/viewinformation2d.cxx')
-rw-r--r-- | drawinglayer/source/geometry/viewinformation2d.cxx | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/drawinglayer/source/geometry/viewinformation2d.cxx b/drawinglayer/source/geometry/viewinformation2d.cxx new file mode 100644 index 0000000000..03089e41e3 --- /dev/null +++ b/drawinglayer/source/geometry/viewinformation2d.cxx @@ -0,0 +1,458 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <drawinglayer/geometry/viewinformation2d.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/utils/canvastools.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/drawing/XDrawPage.hpp> +#include <com/sun/star/geometry/AffineMatrix2D.hpp> +#include <com/sun/star/geometry/RealRectangle2D.hpp> +#include <o3tl/temporary.hxx> +#include <officecfg/Office/Common.hxx> +#include <unotools/configmgr.hxx> + +#include <atomic> +#include <utility> + +using namespace com::sun::star; + +namespace drawinglayer::geometry +{ +namespace +{ +constexpr OUStringLiteral g_PropertyName_ObjectTransformation = u"ObjectTransformation"; +constexpr OUStringLiteral g_PropertyName_ViewTransformation = u"ViewTransformation"; +constexpr OUStringLiteral g_PropertyName_Viewport = u"Viewport"; +constexpr OUStringLiteral g_PropertyName_Time = u"Time"; +constexpr OUStringLiteral g_PropertyName_VisualizedPage = u"VisualizedPage"; +constexpr OUStringLiteral g_PropertyName_ReducedDisplayQuality = u"ReducedDisplayQuality"; +constexpr OUStringLiteral g_PropertyName_UseAntiAliasing = u"UseAntiAliasing"; +constexpr OUStringLiteral g_PropertyName_PixelSnapHairline = u"PixelSnapHairline"; +} + +namespace +{ +bool bForwardsAreInitialized(false); +bool bForwardPixelSnapHairline(true); +} + +class ImpViewInformation2D +{ +private: + // ViewInformation2D implementation can change refcount, so we have only + // two memory regions for pairs of ViewInformation2D/ImpViewInformation2D + friend class ::drawinglayer::geometry::ViewInformation2D; + +protected: + // the object transformation + basegfx::B2DHomMatrix maObjectTransformation; + + // the view transformation + basegfx::B2DHomMatrix maViewTransformation; + + // the ObjectToView and it's inverse, both on demand from ObjectTransformation + // and ViewTransformation + basegfx::B2DHomMatrix maObjectToViewTransformation; + basegfx::B2DHomMatrix maInverseObjectToViewTransformation; + + // the visible range and the on-demand one in ViewCoordinates + basegfx::B2DRange maViewport; + basegfx::B2DRange maDiscreteViewport; + + // the DrawPage which is target of visualisation. This is needed e.g. for + // the view-dependent decomposition of PageNumber TextFields. + // This parameter is buffered here, but mainly resides in mxExtendedInformation, + // so it will be interpreted, but held there. It will also not be added + // to mxExtendedInformation in impFillViewInformationFromContent (it's there already) + uno::Reference<drawing::XDrawPage> mxVisualizedPage; + + // the point in time + double mfViewTime; + + // allow to reduce DisplayQuality (e.g. sw 3d fallback renderer for interactions) + bool mbReducedDisplayQuality : 1; + + // determine if to use AntiAliasing on target pixel device + bool mbUseAntiAliasing : 1; + + // determine if to use PixelSnapHairline on target pixel device + bool mbPixelSnapHairline : 1; + +public: + ImpViewInformation2D() + : maObjectTransformation() + , maViewTransformation() + , maObjectToViewTransformation() + , maInverseObjectToViewTransformation() + , maViewport() + , maDiscreteViewport() + , mxVisualizedPage() + , mfViewTime(0.0) + , mbReducedDisplayQuality(false) + , mbUseAntiAliasing(ViewInformation2D::getGlobalAntiAliasing()) + , mbPixelSnapHairline(mbUseAntiAliasing && bForwardPixelSnapHairline) + { + } + + const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; } + void setObjectTransformation(const basegfx::B2DHomMatrix& rNew) + { + maObjectTransformation = rNew; + maObjectToViewTransformation.identity(); + maInverseObjectToViewTransformation.identity(); + } + + const basegfx::B2DHomMatrix& getViewTransformation() const { return maViewTransformation; } + void setViewTransformation(const basegfx::B2DHomMatrix& rNew) + { + maViewTransformation = rNew; + maDiscreteViewport.reset(); + maObjectToViewTransformation.identity(); + maInverseObjectToViewTransformation.identity(); + } + + const basegfx::B2DRange& getViewport() const { return maViewport; } + void setViewport(const basegfx::B2DRange& rNew) + { + maViewport = rNew; + maDiscreteViewport.reset(); + } + + const basegfx::B2DRange& getDiscreteViewport() const + { + if (maDiscreteViewport.isEmpty() && !maViewport.isEmpty()) + { + basegfx::B2DRange aDiscreteViewport(maViewport); + aDiscreteViewport.transform(getViewTransformation()); + const_cast<ImpViewInformation2D*>(this)->maDiscreteViewport = aDiscreteViewport; + } + + return maDiscreteViewport; + } + + const basegfx::B2DHomMatrix& getObjectToViewTransformation() const + { + if (maObjectToViewTransformation.isIdentity() + && (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity())) + { + basegfx::B2DHomMatrix aObjectToView(maViewTransformation * maObjectTransformation); + const_cast<ImpViewInformation2D*>(this)->maObjectToViewTransformation = aObjectToView; + } + + return maObjectToViewTransformation; + } + + const basegfx::B2DHomMatrix& getInverseObjectToViewTransformation() const + { + if (maInverseObjectToViewTransformation.isIdentity() + && (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity())) + { + basegfx::B2DHomMatrix aInverseObjectToView(maViewTransformation + * maObjectTransformation); + aInverseObjectToView.invert(); + const_cast<ImpViewInformation2D*>(this)->maInverseObjectToViewTransformation + = aInverseObjectToView; + } + + return maInverseObjectToViewTransformation; + } + + double getViewTime() const { return mfViewTime; } + void setViewTime(double fNew) + { + if (fNew >= 0.0) + { + mfViewTime = fNew; + } + } + + const uno::Reference<drawing::XDrawPage>& getVisualizedPage() const { return mxVisualizedPage; } + void setVisualizedPage(const uno::Reference<drawing::XDrawPage>& rNew) + { + mxVisualizedPage = rNew; + } + + bool getReducedDisplayQuality() const { return mbReducedDisplayQuality; } + void setReducedDisplayQuality(bool bNew) { mbReducedDisplayQuality = bNew; } + + bool getUseAntiAliasing() const { return mbUseAntiAliasing; } + void setUseAntiAliasing(bool bNew) { mbUseAntiAliasing = bNew; } + + bool getPixelSnapHairline() const { return mbPixelSnapHairline; } + void setPixelSnapHairline(bool bNew) { mbPixelSnapHairline = bNew; } + + bool operator==(const ImpViewInformation2D& rCandidate) const + { + return (maObjectTransformation == rCandidate.maObjectTransformation + && maViewTransformation == rCandidate.maViewTransformation + && maViewport == rCandidate.maViewport + && mxVisualizedPage == rCandidate.mxVisualizedPage + && mfViewTime == rCandidate.mfViewTime + && mbReducedDisplayQuality == rCandidate.mbReducedDisplayQuality + && mbUseAntiAliasing == rCandidate.mbUseAntiAliasing + && mbPixelSnapHairline == rCandidate.mbPixelSnapHairline); + } +}; + +namespace +{ +ViewInformation2D::ImplType& theGlobalDefault() +{ + static ViewInformation2D::ImplType SINGLETON; + return SINGLETON; +} +} + +ViewInformation2D::ViewInformation2D() + : mpViewInformation2D(theGlobalDefault()) +{ + if (!bForwardsAreInitialized) + { + bForwardsAreInitialized = true; + if (!utl::ConfigManager::IsFuzzing()) + { + bForwardPixelSnapHairline + = officecfg::Office::Common::Drawinglayer::SnapHorVerLinesToDiscrete::get(); + } + } + + setUseAntiAliasing(ViewInformation2D::getGlobalAntiAliasing()); + setPixelSnapHairline(bForwardPixelSnapHairline); +} + +ViewInformation2D::ViewInformation2D(const ViewInformation2D&) = default; + +ViewInformation2D::ViewInformation2D(ViewInformation2D&&) = default; + +ViewInformation2D::~ViewInformation2D() = default; + +ViewInformation2D& ViewInformation2D::operator=(const ViewInformation2D&) = default; + +ViewInformation2D& ViewInformation2D::operator=(ViewInformation2D&&) = default; + +bool ViewInformation2D::operator==(const ViewInformation2D& rCandidate) const +{ + return rCandidate.mpViewInformation2D == mpViewInformation2D; +} + +const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const +{ + return mpViewInformation2D->getObjectTransformation(); +} + +void ViewInformation2D::setObjectTransformation(const basegfx::B2DHomMatrix& rNew) +{ + if (std::as_const(mpViewInformation2D)->getObjectTransformation() != rNew) + mpViewInformation2D->setObjectTransformation(rNew); +} + +const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const +{ + return mpViewInformation2D->getViewTransformation(); +} + +void ViewInformation2D::setViewTransformation(const basegfx::B2DHomMatrix& rNew) +{ + if (std::as_const(mpViewInformation2D)->getViewTransformation() != rNew) + mpViewInformation2D->setViewTransformation(rNew); +} + +const basegfx::B2DRange& ViewInformation2D::getViewport() const +{ + return mpViewInformation2D->getViewport(); +} + +void ViewInformation2D::setViewport(const basegfx::B2DRange& rNew) +{ + if (rNew != std::as_const(mpViewInformation2D)->getViewport()) + mpViewInformation2D->setViewport(rNew); +} + +double ViewInformation2D::getViewTime() const { return mpViewInformation2D->getViewTime(); } + +void ViewInformation2D::setViewTime(double fNew) +{ + if (fNew != std::as_const(mpViewInformation2D)->getViewTime()) + mpViewInformation2D->setViewTime(fNew); +} + +const uno::Reference<drawing::XDrawPage>& ViewInformation2D::getVisualizedPage() const +{ + return mpViewInformation2D->getVisualizedPage(); +} + +void ViewInformation2D::setVisualizedPage(const uno::Reference<drawing::XDrawPage>& rNew) +{ + if (rNew != std::as_const(mpViewInformation2D)->getVisualizedPage()) + mpViewInformation2D->setVisualizedPage(rNew); +} + +const basegfx::B2DHomMatrix& ViewInformation2D::getObjectToViewTransformation() const +{ + return mpViewInformation2D->getObjectToViewTransformation(); +} + +const basegfx::B2DHomMatrix& ViewInformation2D::getInverseObjectToViewTransformation() const +{ + return mpViewInformation2D->getInverseObjectToViewTransformation(); +} + +const basegfx::B2DRange& ViewInformation2D::getDiscreteViewport() const +{ + return mpViewInformation2D->getDiscreteViewport(); +} + +bool ViewInformation2D::getReducedDisplayQuality() const +{ + return mpViewInformation2D->getReducedDisplayQuality(); +} + +void ViewInformation2D::setReducedDisplayQuality(bool bNew) +{ + if (bNew != std::as_const(mpViewInformation2D)->getReducedDisplayQuality()) + mpViewInformation2D->setReducedDisplayQuality(bNew); +} + +bool ViewInformation2D::getUseAntiAliasing() const +{ + return mpViewInformation2D->getUseAntiAliasing(); +} + +void ViewInformation2D::setUseAntiAliasing(bool bNew) +{ + if (bNew != std::as_const(mpViewInformation2D)->getUseAntiAliasing()) + mpViewInformation2D->setUseAntiAliasing(bNew); +} + +bool ViewInformation2D::getPixelSnapHairline() const +{ + return mpViewInformation2D->getPixelSnapHairline(); +} + +void ViewInformation2D::setPixelSnapHairline(bool bNew) +{ + if (bNew != std::as_const(mpViewInformation2D)->getPixelSnapHairline()) + mpViewInformation2D->setPixelSnapHairline(bNew); +} + +static std::atomic<bool>& globalAntiAliasing() +{ + static std::atomic<bool> g_GlobalAntiAliasing + = utl::ConfigManager::IsFuzzing() + || officecfg::Office::Common::Drawinglayer::AntiAliasing::get(); + return g_GlobalAntiAliasing; +} + +/** + * Some code like to turn this stuff on and off during a drawing operation + * so it can "tunnel" information down through several layers, + * so we don't want to actually do a config write all the time. + */ +void ViewInformation2D::setGlobalAntiAliasing(bool bAntiAliasing, bool bTemporary) +{ + if (globalAntiAliasing().compare_exchange_strong(o3tl::temporary(!bAntiAliasing), bAntiAliasing) + && !bTemporary) + { + auto batch = comphelper::ConfigurationChanges::create(); + officecfg::Office::Common::Drawinglayer::AntiAliasing::set(bAntiAliasing, batch); + batch->commit(); + } +} +bool ViewInformation2D::getGlobalAntiAliasing() { return globalAntiAliasing(); } + +void ViewInformation2D::forwardPixelSnapHairline(bool bPixelSnapHairline) +{ + bForwardPixelSnapHairline = bPixelSnapHairline; +} + +ViewInformation2D +createViewInformation2D(const css::uno::Sequence<css::beans::PropertyValue>& rViewParameters) +{ + if (!rViewParameters.hasElements()) + return ViewInformation2D(); + + ViewInformation2D aRetval; + + for (auto const& rPropertyValue : rViewParameters) + { + if (rPropertyValue.Name == g_PropertyName_ReducedDisplayQuality) + { + bool bNew(false); + rPropertyValue.Value >>= bNew; + aRetval.setReducedDisplayQuality(bNew); + } + else if (rPropertyValue.Name == g_PropertyName_PixelSnapHairline) + { + bool bNew( + true); //SvtOptionsDrawinglayer::IsAntiAliasing() && SvtOptionsDrawinglayer::IsSnapHorVerLinesToDiscrete()); + rPropertyValue.Value >>= bNew; + aRetval.setPixelSnapHairline(bNew); + } + else if (rPropertyValue.Name == g_PropertyName_UseAntiAliasing) + { + bool bNew(true); //SvtOptionsDrawinglayer::IsAntiAliasing()); + rPropertyValue.Value >>= bNew; + aRetval.setUseAntiAliasing(bNew); + } + else if (rPropertyValue.Name == g_PropertyName_ObjectTransformation) + { + css::geometry::AffineMatrix2D aAffineMatrix2D; + rPropertyValue.Value >>= aAffineMatrix2D; + basegfx::B2DHomMatrix aTransformation; + basegfx::unotools::homMatrixFromAffineMatrix(aTransformation, aAffineMatrix2D); + aRetval.setObjectTransformation(aTransformation); + } + else if (rPropertyValue.Name == g_PropertyName_ViewTransformation) + { + css::geometry::AffineMatrix2D aAffineMatrix2D; + rPropertyValue.Value >>= aAffineMatrix2D; + basegfx::B2DHomMatrix aTransformation; + basegfx::unotools::homMatrixFromAffineMatrix(aTransformation, aAffineMatrix2D); + aRetval.setViewTransformation(aTransformation); + } + else if (rPropertyValue.Name == g_PropertyName_Viewport) + { + css::geometry::RealRectangle2D aUnoViewport; + rPropertyValue.Value >>= aUnoViewport; + const basegfx::B2DRange aViewport( + basegfx::unotools::b2DRectangleFromRealRectangle2D(aUnoViewport)); + aRetval.setViewport(aViewport); + } + else if (rPropertyValue.Name == g_PropertyName_Time) + { + double fViewTime(0.0); + rPropertyValue.Value >>= fViewTime; + aRetval.setViewTime(fViewTime); + } + else if (rPropertyValue.Name == g_PropertyName_VisualizedPage) + { + css::uno::Reference<css::drawing::XDrawPage> xVisualizedPage; + rPropertyValue.Value >>= xVisualizedPage; + aRetval.setVisualizedPage(xVisualizedPage); + } + } + + return aRetval; +} + +} // end of namespace drawinglayer::geometry + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |