/* -*- 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 .
*/
/** Wrapper around a sprite that is displayed on a PresenterCanvas.
*/ namespace { typedef comphelper::WeakComponentImplHelper <
css::rendering::XCustomSprite
> PresenterCustomSpriteInterfaceBase;
class PresenterCustomSprite final
: public PresenterCustomSpriteInterfaceBase
{ public:
PresenterCustomSprite (
rtl::Reference<PresenterCanvas> pCanvas, const Reference<rendering::XCustomSprite>& rxSprite, const Reference<awt::XWindow>& rxBaseWindow);
PresenterCustomSprite(const PresenterCustomSprite&) = delete;
PresenterCustomSprite& operator=(const PresenterCustomSprite&) = delete; virtualvoid disposing(std::unique_lock<std::mutex>&) override;
void SAL_CALL PresenterCanvas::clear()
{
ThrowIfDisposed(); // ToDo: Clear the area covered by the child window. A simple forward // would clear the whole shared canvas.
}
rendering::ViewState PresenterCanvas::MergeViewState ( const rendering::ViewState& rViewState)
{ // Make sure the offset is up-to-date. if (mbOffsetUpdatePending)
maOffset = GetOffset(mxSharedWindow); return MergeViewState(rViewState, maOffset);
}
css::rendering::ViewState PresenterCanvas::MergeViewState ( const css::rendering::ViewState& rViewState, const css::awt::Point& rOffset)
{ // Early rejects. if ( ! mxSharedCanvas.is()) return rViewState;
Reference<rendering::XGraphicDevice> xDevice (mxSharedCanvas->getDevice()); if ( ! xDevice.is()) return rViewState;
// Create a modifiable copy of the given view state.
rendering::ViewState aViewState (rViewState);
// Prepare the local clip rectangle.
::basegfx::B2DRectangle aWindowRange (GetClipRectangle(aViewState.AffineTransform, rOffset));
// Adapt the offset of the view state.
aViewState.AffineTransform.m02 += rOffset.X;
aViewState.AffineTransform.m12 += rOffset.Y;
// Adapt the clip polygon. if ( ! aViewState.Clip.is())
{ // Cancel out the later multiplication with the view state // transformation.
aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
xDevice,
::basegfx::B2DPolyPolygon(::basegfx::utils::createPolygonFromRect(aWindowRange)));
} else
{ // Have to compute the intersection of the given clipping polygon in // the view state and the local clip rectangle.
// Clip the view state clipping polygon against the local clip rectangle. const ::basegfx::B2DPolyPolygon aClipPolygon (
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(
aViewState.Clip)); const ::basegfx::B2DPolyPolygon aClippedClipPolygon (
::basegfx::utils::clipPolyPolygonOnRange(
aClipPolygon,
aWindowRange, true, /* bInside */ false/* bStroke */));
VclPtr<vcl::Window> pSharedWindow = VCLUnoHelper::GetWindow(mxSharedWindow); if (!pSharedWindow) return ::basegfx::B2DRectangle();
// Get the bounding box of the window and create a range in the // coordinate system of the child window. // Use the window extents.
::tools::Rectangle aLocalClip = pWindow->GetWindowExtentsRelative(*pSharedWindow);
// The local clip rectangle is used to clip the view state clipping // polygon.
::basegfx::B2DRectangle aWindowRectangle (
aLocalClip.Left() - rOffset.X,
aLocalClip.Top() - rOffset.Y,
aLocalClip.Right() - rOffset.X + 1,
aLocalClip.Bottom() - rOffset.Y + 1);
// Calculate the inverted view state transformation to cancel out a // later transformation of the local clip polygon with the view state // transformation.
::basegfx::B2DHomMatrix aInvertedViewStateTransformation;
::basegfx::unotools::homMatrixFromAffineMatrix(
aInvertedViewStateTransformation,
rViewTransform); if (aInvertedViewStateTransformation.invert())
{ // Cancel out the later multiplication with the view state // transformation.
aWindowRectangle.transform(aInvertedViewStateTransformation);
}
return aWindowRectangle;
}
Reference<rendering::XPolyPolygon2D> PresenterCanvas::UpdateSpriteClip ( const Reference<rendering::XPolyPolygon2D>& rxOriginalClip, const geometry::RealPoint2D& rLocation)
{ // Check used resources and just return the original clip when not // every one of them is available. if ( ! mxWindow.is()) return rxOriginalClip;
Reference<rendering::XGraphicDevice> xDevice (mxSharedCanvas->getDevice()); if ( ! xDevice.is()) return rxOriginalClip;
// Determine the bounds of the clip rectangle (the window border) in the // coordinate system of the sprite. const awt::Rectangle aWindowBox (mxWindow->getPosSize()); constdouble nMinX (-rLocation.X); constdouble nMinY (-rLocation.Y); constdouble nMaxX (aWindowBox.Width-rLocation.X); constdouble nMaxY (aWindowBox.Height-rLocation.Y);
// Create a clip polygon.
Reference<rendering::XPolyPolygon2D> xPolygon; if (rxOriginalClip.is())
{ // Combine the original clip with the window clip. const ::basegfx::B2DPolyPolygon aOriginalClip (
::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rxOriginalClip));
::basegfx::B2DRectangle aWindowRange (nMinX, nMinY, nMaxX, nMaxY); const ::basegfx::B2DPolyPolygon aClippedClipPolygon (
::basegfx::utils::clipPolyPolygonOnRange(
aOriginalClip,
aWindowRange, true, /* bInside */ false/* bStroke */));
xPolygon = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
xDevice,
aClippedClipPolygon);
} else
{ // Create a new clip polygon from the window clip rectangle.
Sequence<Sequence<geometry::RealPoint2D> > aPoints
{
{
{ nMinX,nMinY },
{ nMaxX,nMinY },
{ nMaxX,nMaxY },
{ nMinX,nMaxY }
}
};
Reference<rendering::XLinePolyPolygon2D> xLinePolygon(
xDevice->createCompatibleLinePolyPolygon(aPoints)); if (xLinePolygon.is())
xLinePolygon->setClosed(0, true);
xPolygon = xLinePolygon;
}
return xPolygon;
}
void PresenterCanvas::ThrowIfDisposed()
{ if (m_bDisposed || ! mxSharedCanvas.is())
{ throw lang::DisposedException (u"PresenterCanvas object has already been disposed"_ustr, static_cast<uno::XWeak*>(this));
}
}
void SAL_CALL PresenterCustomSprite::move ( const geometry::RealPoint2D& rNewPos, const rendering::ViewState& rViewState, const rendering::RenderState& rRenderState)
{
ThrowIfDisposed();
maPosition = rNewPos;
mxSprite->move(
rNewPos,
mpCanvas->MergeViewState(rViewState, mpCanvas->GetOffset(mxBaseWindow)),
rRenderState); // Clip sprite against window bounds. This call is necessary because // sprite clipping is done in the coordinate system of the sprite. // Therefore, after each change of the sprites location the window // bounds have to be transformed into the sprites coordinate system.
clip(nullptr);
}
void SAL_CALL PresenterCustomSprite::clip (const Reference<rendering::XPolyPolygon2D>& rxClip)
{
ThrowIfDisposed(); // The clip region is expected in the coordinate system of the sprite. // UpdateSpriteClip() integrates the window bounds, transformed into the // sprites coordinate system, with the given clip.
mxSprite->clip(mpCanvas->UpdateSpriteClip(rxClip, maPosition));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.