blob: 641ef1926842642608ccb52017846a316f592886 [file] [log] [blame]
/**************************************************************
*
* 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
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_drawinglayer.hxx"
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/range/b2drange.hxx>
#include <osl/mutex.hxx>
#include <basegfx/tools/canvastools.hxx>
#include <com/sun/star/geometry/AffineMatrix2D.hpp>
#include <com/sun/star/geometry/RealRectangle2D.hpp>
//////////////////////////////////////////////////////////////////////////////
using namespace com::sun::star;
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace geometry
{
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;
// the refcounter. 0 means exclusively used
sal_uInt32 mnRefCount;
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;
// bitfield
bool mbReducedDisplayQuality : 1;
// the complete PropertyValue representation (if already created)
uno::Sequence< beans::PropertyValue > mxViewInformation;
// the extra PropertyValues; not represented by ViewTransformation,
// Viewport, VisualizedPage or ViewTime
uno::Sequence< beans::PropertyValue > mxExtendedInformation;
// the local UNO API strings
const ::rtl::OUString& getNamePropertyObjectTransformation()
{
static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
return s_sNameProperty;
}
const ::rtl::OUString& getNamePropertyViewTransformation()
{
static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ViewTransformation"));
return s_sNameProperty;
}
const ::rtl::OUString& getNamePropertyViewport()
{
static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Viewport"));
return s_sNameProperty;
}
const ::rtl::OUString& getNamePropertyTime()
{
static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Time"));
return s_sNameProperty;
}
const ::rtl::OUString& getNamePropertyVisualizedPage()
{
static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("VisualizedPage"));
return s_sNameProperty;
}
const ::rtl::OUString& getNamePropertyReducedDisplayQuality()
{
static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality"));
return s_sNameProperty;
}
void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
{
if(rViewParameters.hasElements())
{
const sal_Int32 nCount(rViewParameters.getLength());
sal_Int32 nExtendedInsert(0);
// prepare extended information for filtering. Maximum size is nCount
mxExtendedInformation.realloc(nCount);
for(sal_Int32 a(0); a < nCount; a++)
{
const beans::PropertyValue& rProp = rViewParameters[a];
if(rProp.Name == getNamePropertyReducedDisplayQuality())
{
// extra information; add to filtered information
mxExtendedInformation[nExtendedInsert++] = rProp;
// for performance reasons, also cache content locally
sal_Bool bSalBool(false);
rProp.Value >>= bSalBool;
mbReducedDisplayQuality = bSalBool;
}
else if(rProp.Name == getNamePropertyObjectTransformation())
{
com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
rProp.Value >>= aAffineMatrix2D;
basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation, aAffineMatrix2D);
}
else if(rProp.Name == getNamePropertyViewTransformation())
{
com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
rProp.Value >>= aAffineMatrix2D;
basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, aAffineMatrix2D);
}
else if(rProp.Name == getNamePropertyViewport())
{
com::sun::star::geometry::RealRectangle2D aViewport;
rProp.Value >>= aViewport;
maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport);
}
else if(rProp.Name == getNamePropertyTime())
{
rProp.Value >>= mfViewTime;
}
else if(rProp.Name == getNamePropertyVisualizedPage())
{
rProp.Value >>= mxVisualizedPage;
}
else
{
// extra information; add to filtered information
mxExtendedInformation[nExtendedInsert++] = rProp;
}
}
// extra information size is now known; realloc to final size
mxExtendedInformation.realloc(nExtendedInsert);
}
}
void impFillViewInformationFromContent()
{
uno::Sequence< beans::PropertyValue > xRetval;
const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
const bool bViewTransformationUsed(!maViewTransformation.isIdentity());
const bool bViewportUsed(!maViewport.isEmpty());
const bool bTimeUsed(0.0 < mfViewTime);
const bool bVisualizedPageUsed(mxVisualizedPage.is());
const bool bReducedDisplayQualityUsed(true == mbReducedDisplayQuality);
const bool bExtraInformation(mxExtendedInformation.hasElements());
sal_uInt32 nIndex(0);
const sal_uInt32 nCount(
(bObjectTransformationUsed ? 1 : 0) +
(bViewTransformationUsed ? 1 : 0) +
(bViewportUsed ? 1 : 0) +
(bTimeUsed ? 1 : 0) +
(bVisualizedPageUsed ? 1 : 0) +
(bReducedDisplayQualityUsed ? 1 : 0) +
(bExtraInformation ? mxExtendedInformation.getLength() : 0));
mxViewInformation.realloc(nCount);
if(bObjectTransformationUsed)
{
com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maObjectTransformation);
mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
nIndex++;
}
if(bViewTransformationUsed)
{
com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maViewTransformation);
mxViewInformation[nIndex].Name = getNamePropertyViewTransformation();
mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
nIndex++;
}
if(bViewportUsed)
{
const com::sun::star::geometry::RealRectangle2D aViewport(basegfx::unotools::rectangle2DFromB2DRectangle(maViewport));
mxViewInformation[nIndex].Name = getNamePropertyViewport();
mxViewInformation[nIndex].Value <<= aViewport;
nIndex++;
}
if(bTimeUsed)
{
mxViewInformation[nIndex].Name = getNamePropertyTime();
mxViewInformation[nIndex].Value <<= mfViewTime;
nIndex++;
}
if(bVisualizedPageUsed)
{
mxViewInformation[nIndex].Name = getNamePropertyVisualizedPage();
mxViewInformation[nIndex].Value <<= mxVisualizedPage;
nIndex++;
}
if(bExtraInformation)
{
const sal_Int32 nExtra(mxExtendedInformation.getLength());
for(sal_Int32 a(0); a < nExtra; a++)
{
mxViewInformation[nIndex++] = mxExtendedInformation[a];
}
}
}
public:
ImpViewInformation2D(
const basegfx::B2DHomMatrix& rObjectTransformation,
const basegfx::B2DHomMatrix& rViewTransformation,
const basegfx::B2DRange& rViewport,
const uno::Reference< drawing::XDrawPage >& rxDrawPage,
double fViewTime,
const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
: mnRefCount(0),
maObjectTransformation(rObjectTransformation),
maViewTransformation(rViewTransformation),
maObjectToViewTransformation(),
maInverseObjectToViewTransformation(),
maViewport(rViewport),
maDiscreteViewport(),
mxVisualizedPage(rxDrawPage),
mfViewTime(fViewTime),
mbReducedDisplayQuality(false),
mxViewInformation(),
mxExtendedInformation()
{
impInterpretPropertyValues(rExtendedParameters);
}
ImpViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
: mnRefCount(0),
maObjectTransformation(),
maViewTransformation(),
maObjectToViewTransformation(),
maInverseObjectToViewTransformation(),
maViewport(),
maDiscreteViewport(),
mxVisualizedPage(),
mfViewTime(),
mbReducedDisplayQuality(false),
mxViewInformation(rViewParameters),
mxExtendedInformation()
{
impInterpretPropertyValues(rViewParameters);
}
ImpViewInformation2D()
: mnRefCount(0),
maObjectTransformation(),
maViewTransformation(),
maObjectToViewTransformation(),
maInverseObjectToViewTransformation(),
maViewport(),
maDiscreteViewport(),
mxVisualizedPage(),
mfViewTime(),
mbReducedDisplayQuality(false),
mxViewInformation(),
mxExtendedInformation()
{
}
const basegfx::B2DHomMatrix& getObjectTransformation() const
{
return maObjectTransformation;
}
const basegfx::B2DHomMatrix& getViewTransformation() const
{
return maViewTransformation;
}
const basegfx::B2DRange& getViewport() const
{
return maViewport;
}
const basegfx::B2DRange& getDiscreteViewport() const
{
::osl::Mutex m_mutex;
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
{
::osl::Mutex m_mutex;
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
{
::osl::Mutex m_mutex;
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;
}
const uno::Reference< drawing::XDrawPage >& getVisualizedPage() const
{
return mxVisualizedPage;
}
bool getReducedDisplayQuality() const
{
return mbReducedDisplayQuality;
}
const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
{
if(!mxViewInformation.hasElements())
{
const_cast< ImpViewInformation2D* >(this)->impFillViewInformationFromContent();
}
return mxViewInformation;
}
const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
{
return mxExtendedInformation;
}
bool operator==(const ImpViewInformation2D& rCandidate) const
{
return (maObjectTransformation == rCandidate.maObjectTransformation
&& maViewTransformation == rCandidate.maViewTransformation
&& maViewport == rCandidate.maViewport
&& mxVisualizedPage == rCandidate.mxVisualizedPage
&& mfViewTime == rCandidate.mfViewTime
&& mxExtendedInformation == rCandidate.mxExtendedInformation);
}
static ImpViewInformation2D* get_global_default()
{
static ImpViewInformation2D* pDefault = 0;
if(!pDefault)
{
pDefault = new ImpViewInformation2D();
// never delete; start with RefCount 1, not 0
pDefault->mnRefCount++;
}
return pDefault;
}
};
} // end of anonymous namespace
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace geometry
{
ViewInformation2D::ViewInformation2D(
const basegfx::B2DHomMatrix& rObjectTransformation,
const basegfx::B2DHomMatrix& rViewTransformation,
const basegfx::B2DRange& rViewport,
const uno::Reference< drawing::XDrawPage >& rxDrawPage,
double fViewTime,
const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
: mpViewInformation2D(new ImpViewInformation2D(
rObjectTransformation,
rViewTransformation,
rViewport,
rxDrawPage,
fViewTime,
rExtendedParameters))
{
}
ViewInformation2D::ViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
: mpViewInformation2D(new ImpViewInformation2D(rViewParameters))
{
}
ViewInformation2D::ViewInformation2D()
: mpViewInformation2D(ImpViewInformation2D::get_global_default())
{
mpViewInformation2D->mnRefCount++;
}
ViewInformation2D::ViewInformation2D(const ViewInformation2D& rCandidate)
: mpViewInformation2D(rCandidate.mpViewInformation2D)
{
::osl::Mutex m_mutex;
mpViewInformation2D->mnRefCount++;
}
ViewInformation2D::~ViewInformation2D()
{
::osl::Mutex m_mutex;
if(mpViewInformation2D->mnRefCount)
{
mpViewInformation2D->mnRefCount--;
}
else
{
delete mpViewInformation2D;
}
}
bool ViewInformation2D::isDefault() const
{
return mpViewInformation2D == ImpViewInformation2D::get_global_default();
}
ViewInformation2D& ViewInformation2D::operator=(const ViewInformation2D& rCandidate)
{
::osl::Mutex m_mutex;
if(mpViewInformation2D->mnRefCount)
{
mpViewInformation2D->mnRefCount--;
}
else
{
delete mpViewInformation2D;
}
mpViewInformation2D = rCandidate.mpViewInformation2D;
mpViewInformation2D->mnRefCount++;
return *this;
}
bool ViewInformation2D::operator==(const ViewInformation2D& rCandidate) const
{
if(rCandidate.mpViewInformation2D == mpViewInformation2D)
{
return true;
}
if(rCandidate.isDefault() != isDefault())
{
return false;
}
return (*rCandidate.mpViewInformation2D == *mpViewInformation2D);
}
const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const
{
return mpViewInformation2D->getObjectTransformation();
}
const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const
{
return mpViewInformation2D->getViewTransformation();
}
const basegfx::B2DRange& ViewInformation2D::getViewport() const
{
return mpViewInformation2D->getViewport();
}
double ViewInformation2D::getViewTime() const
{
return mpViewInformation2D->getViewTime();
}
const uno::Reference< drawing::XDrawPage >& ViewInformation2D::getVisualizedPage() const
{
return mpViewInformation2D->getVisualizedPage();
}
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();
}
const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getViewInformationSequence() const
{
return mpViewInformation2D->getViewInformationSequence();
}
const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getExtendedInformationSequence() const
{
return mpViewInformation2D->getExtendedInformationSequence();
}
} // end of namespace geometry
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
// eof