/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include 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 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(this)->maDiscreteViewport = aDiscreteViewport; } return maDiscreteViewport; } const basegfx::B2DHomMatrix& getObjectToViewTransformation() const { if (maObjectToViewTransformation.isIdentity() && (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity())) { basegfx::B2DHomMatrix aObjectToView(maViewTransformation * maObjectTransformation); const_cast(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(this)->maInverseObjectToViewTransformation = aInverseObjectToView; } return maInverseObjectToViewTransformation; } double getViewTime() const { return mfViewTime; } void setViewTime(double fNew) { if (fNew >= 0.0) { mfViewTime = fNew; } } const uno::Reference& getVisualizedPage() const { return mxVisualizedPage; } void setVisualizedPage(const uno::Reference& 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& ViewInformation2D::getVisualizedPage() const { return mpViewInformation2D->getVisualizedPage(); } void ViewInformation2D::setVisualizedPage(const uno::Reference& 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& globalAntiAliasing() { static std::atomic 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& 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 xVisualizedPage; rPropertyValue.Value >>= xVisualizedPage; aRetval.setVisualizedPage(xVisualizedPage); } } return aRetval; } } // end of namespace drawinglayer::geometry /* vim:set shiftwidth=4 softtabstop=4 expandtab: */