494 lines
18 KiB
C++
494 lines
18 KiB
C++
/* -*- 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";
|
|
}
|
|
|
|
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;
|
|
|
|
// color to use for automatic color
|
|
Color maAutoColor;
|
|
|
|
// a hint that the View that is being painted has an active TextEdit. This
|
|
// is important for handling of TextHierarchyEditPrimitive2D to suppress
|
|
// the text for objects in TextEdit - the text is visualized by the
|
|
// active EditEngine/Outliner overlay, so it would be double visualized
|
|
bool mbTextEditActive : 1;
|
|
|
|
// processed view is an EditView
|
|
bool mbEditViewActive : 1;
|
|
|
|
// 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)
|
|
, maAutoColor(COL_AUTO)
|
|
, mbTextEditActive(false)
|
|
, mbEditViewActive(false)
|
|
, mbReducedDisplayQuality(false)
|
|
, mbUseAntiAliasing(ViewInformation2D::getGlobalAntiAliasing())
|
|
{
|
|
if (comphelper::IsFuzzing())
|
|
mbPixelSnapHairline = false;
|
|
else
|
|
mbPixelSnapHairline
|
|
= mbUseAntiAliasing
|
|
&& officecfg::Office::Common::Drawinglayer::SnapHorVerLinesToDiscrete::get();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
Color getAutoColor() const { return maAutoColor; }
|
|
void setAutoColor(Color aNew) { maAutoColor = aNew; }
|
|
|
|
bool getTextEditActive() const { return mbTextEditActive; }
|
|
void setTextEditActive(bool bNew) { mbTextEditActive = bNew; }
|
|
|
|
bool getEditViewActive() const { return mbEditViewActive; }
|
|
void setEditViewActive(bool bNew) { mbEditViewActive = bNew; }
|
|
|
|
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 && maAutoColor == rCandidate.maAutoColor
|
|
&& mbTextEditActive == rCandidate.mbTextEditActive
|
|
&& mbEditViewActive == rCandidate.mbEditViewActive
|
|
&& mbReducedDisplayQuality == rCandidate.mbReducedDisplayQuality
|
|
&& mbUseAntiAliasing == rCandidate.mbUseAntiAliasing
|
|
&& mbPixelSnapHairline == rCandidate.mbPixelSnapHairline);
|
|
}
|
|
};
|
|
|
|
namespace
|
|
{
|
|
ViewInformation2D::ImplType& theGlobalDefault()
|
|
{
|
|
static ViewInformation2D::ImplType SINGLETON;
|
|
return SINGLETON;
|
|
}
|
|
}
|
|
|
|
ViewInformation2D::ViewInformation2D()
|
|
: mpViewInformation2D(theGlobalDefault())
|
|
{
|
|
setUseAntiAliasing(ViewInformation2D::getGlobalAntiAliasing());
|
|
if (!comphelper::IsFuzzing())
|
|
setPixelSnapHairline(
|
|
getUseAntiAliasing()
|
|
&& officecfg::Office::Common::Drawinglayer::SnapHorVerLinesToDiscrete::get());
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
Color ViewInformation2D::getAutoColor() const { return mpViewInformation2D->getAutoColor(); }
|
|
|
|
void ViewInformation2D::setAutoColor(Color aNew) { mpViewInformation2D->setAutoColor(aNew); }
|
|
|
|
bool ViewInformation2D::getTextEditActive() const
|
|
{
|
|
return mpViewInformation2D->getTextEditActive();
|
|
}
|
|
|
|
void ViewInformation2D::setTextEditActive(bool bNew)
|
|
{
|
|
mpViewInformation2D->setTextEditActive(bNew);
|
|
}
|
|
|
|
bool ViewInformation2D::getEditViewActive() const
|
|
{
|
|
return mpViewInformation2D->getEditViewActive();
|
|
}
|
|
|
|
void ViewInformation2D::setEditViewActive(bool bNew)
|
|
{
|
|
mpViewInformation2D->setEditViewActive(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
|
|
= comphelper::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(); }
|
|
|
|
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: */
|