Quelle shapeimporter.cxx
Sprache: 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 <utility>
#include <vcl/GraphicObject.hxx>
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <cppcanvas/basegfxfactory.hxx>
#include <cppcanvas/polypolygon.hxx>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/drawing/ColorMode.hpp>
#include <com/sun/star/text/GraphicCrop.hpp>
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/XLayerSupplier.hpp>
#include <com/sun/star/drawing/XLayerManager.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include "drawshape.hxx"
#include "backgroundshape.hxx"
#include "mediashape.hxx"
#include "appletshape.hxx"
#include <shapeimporter.hxx>
#include <slideshowexceptions.hxx>
#include <tools.hxx>
#include <slideshowcontext.hxx>
#include <unoviewcontainer.hxx>
#include <memory>
using namespace com::sun::star;
namespace slideshow::internal {
namespace {
std::unique_ptr<GraphicObject> importShapeGraphic(uno::Reference<beans::XPropertySet> const & xPropSet)
{
std::unique_ptr<GraphicObject> xRet;
uno::Reference<graphic::XGraphic> xGraphic;
if (!getPropertyValue(xGraphic, xPropSet, u"Graphic" _ustr) || !xGraphic.is())
{
// no or empty property - cannot import shape graphic
return xRet;
}
Graphic aGraphic(xGraphic);
xRet.reset(new GraphicObject(std::move(aGraphic)));
if (GraphicType::Default == xRet->GetType() || GraphicType::NONE == xRet->GetType())
{
xRet.reset();
}
return xRet;
}
/** This shape implementation just acts as a dummy for the layermanager.
Its sole role is for hit test detection of group shapes .
*/
class ShapeOfGroup : public Shape
{
public :
ShapeOfGroup( ShapeSharedPtr const & pGroupShape,
uno::Reference<drawing::XShape> xShape,
uno::Reference<beans::XPropertySet> const & xPropSet,
double nPrio );
// Shape:
virtual uno::Reference<drawing::XShape> getXShape() const override;
virtual void addViewLayer( ViewLayerSharedPtr const & pNewLayer,
bool bRedrawLayer ) override;
virtual bool removeViewLayer( ViewLayerSharedPtr const & pNewLayer ) override;
virtual void clearAllViewLayers() override;
virtual bool update() const override;
virtual bool render() const override;
virtual bool isContentChanged() const override;
virtual basegfx::B2DRectangle getBounds() const override;
virtual basegfx::B2DRectangle getDomBounds() const override;
virtual basegfx::B2DRectangle getUpdateArea() const override;
virtual bool isVisible() const override;
virtual double getPriority() const override;
virtual bool isBackgroundDetached() const override;
private :
ShapeSharedPtr const mpGroupShape;
uno::Reference<drawing::XShape> const mxShape;
double const mnPrio;
basegfx::B2DPoint maPosOffset;
double mnWidth;
double mnHeight;
};
ShapeOfGroup::ShapeOfGroup( ShapeSharedPtr const & pGroupShape,
uno::Reference<drawing::XShape> xShape,
uno::Reference<beans::XPropertySet> const & xPropSet,
double nPrio ) :
mpGroupShape(pGroupShape),
mxShape(std::move(xShape)),
mnPrio(nPrio)
{
// read bound rect
uno::Any const aTmpRect_( xPropSet->getPropertyValue( u"BoundRect" _ustr ));
awt::Rectangle const aTmpRect( aTmpRect_.get<awt::Rectangle>() );
basegfx::B2DRectangle const groupPosSize( pGroupShape->getBounds() );
maPosOffset = basegfx::B2DPoint( aTmpRect.X - groupPosSize.getMinX(),
aTmpRect.Y - groupPosSize.getMinY() );
mnWidth = aTmpRect.Width;
mnHeight = aTmpRect.Height;
}
uno::Reference<drawing::XShape> ShapeOfGroup::getXShape() const
{
return mxShape;
}
void ShapeOfGroup::addViewLayer( ViewLayerSharedPtr const & /*pNewLayer*/,
bool /*bRedrawLayer*/ )
{
}
bool ShapeOfGroup::removeViewLayer( ViewLayerSharedPtr const & /*pNewLayer*/ )
{
return true ;
}
void ShapeOfGroup::clearAllViewLayers()
{
}
bool ShapeOfGroup::update() const
{
return true ;
}
bool ShapeOfGroup::render() const
{
return true ;
}
bool ShapeOfGroup::isContentChanged() const
{
return false ;
}
basegfx::B2DRectangle ShapeOfGroup::getBounds() const
{
basegfx::B2DRectangle const groupPosSize( mpGroupShape->getBounds() );
double const posX = groupPosSize.getMinX() + maPosOffset.getX();
double const posY = groupPosSize.getMinY() + maPosOffset.getY();
return basegfx::B2DRectangle( posX, posY, posX + mnWidth, posY + mnHeight );
}
basegfx::B2DRectangle ShapeOfGroup::getDomBounds() const
{
return getBounds();
}
basegfx::B2DRectangle ShapeOfGroup::getUpdateArea() const
{
return getBounds();
}
bool ShapeOfGroup::isVisible() const
{
return mpGroupShape->isVisible();
}
double ShapeOfGroup::getPriority() const
{
return mnPrio;
}
bool ShapeOfGroup::isBackgroundDetached() const
{
return false ;
}
} // anon namespace
ShapeSharedPtr ShapeImporter::createShape(
uno::Reference<drawing::XShape> const & xCurrShape,
uno::Reference<beans::XPropertySet> const & xPropSet,
std::u16string_view shapeType ) const
{
css::uno::Reference<css::drawing::XDrawPage> xPage = mxPage;
if (mbConvertingMasterPage && mbMasterPageObjectsOnly)
{
const XShapesEntry& rTop = maShapesStack.top();
css::uno::Reference<css::drawing::XDrawPage> xMasterPage(rTop.mxShapes, uno::UNO_QUERY_THROW);
if (xMasterPage.is())
xPage = std::move(xMasterPage);
}
if ( shapeType == u"com.sun.star.drawing.MediaShape" || shapeType == u"com.sun.star.presentation.MediaShape" )
{
// Media shape (video etc.). This is a special object
return createMediaShape(xCurrShape,
mnAscendingPrio,
mrContext);
}
else if ( shapeType == u"com.sun.star.drawing.AppletShape" )
{
// PropertyValues to copy from XShape to applet
static const char * aPropertyValues[] =
{
"AppletCodeBase" ,
"AppletName" ,
"AppletCode" ,
"AppletCommands" ,
"AppletIsScript"
};
// (Java)Applet shape. This is a special object
return createAppletShape( xCurrShape,
mnAscendingPrio,
u"com.sun.star.comp.sfx2.AppletObject" _ustr,
aPropertyValues,
SAL_N_ELEMENTS(aPropertyValues),
mrContext );
}
else if ( shapeType == u"com.sun.star.drawing.OLE2Shape" || shapeType == u"com.sun.star.presentation.OLE2Shape" )
{
// #i46224# Mark OLE shapes as foreign content - scan them for
// unsupported actions, and fallback to bitmap, if necessary
return DrawShape::create( xCurrShape,
xPage,
mnAscendingPrio,
true ,
mrContext );
}
else if ( shapeType == u"com.sun.star.drawing.GraphicObjectShape" || shapeType == u"com.sun.star.presentation.GraphicObjectShape" )
{
// to get hold of GIF animations, inspect Graphic
// objects more thoroughly (the plain-jane shape
// metafile of course would only contain the first
// animation frame)
std::unique_ptr<GraphicObject> xGraphicObject(importShapeGraphic(xPropSet));
if (!xGraphicObject)
return ShapeSharedPtr(); // error loading graphic -
// no placeholders in
// slideshow
if (!xGraphicObject->IsAnimated())
{
// no animation - simply utilize plain draw shape import
// import shape as bitmap - either it's a bitmap
// anyway, or it's a metafile, which currently the
// metafile renderer might not display correctly.
return DrawShape::create( xCurrShape,
xPage,
mnAscendingPrio,
true ,
mrContext );
}
// now extract relevant shape attributes via API
drawing::ColorMode eColorMode( drawing::ColorMode_STANDARD );
sal_Int16 nLuminance(0 );
sal_Int16 nContrast(0 );
sal_Int16 nRed(0 );
sal_Int16 nGreen(0 );
sal_Int16 nBlue(0 );
double nGamma(1 .0 );
sal_Int16 nTransparency(0 );
sal_Int32 nRotation(0 );
getPropertyValue( eColorMode, xPropSet, u"GraphicColorMode" _ustr );
getPropertyValue( nLuminance, xPropSet, u"AdjustLuminance" _ustr );
getPropertyValue( nContrast, xPropSet, u"AdjustContrast" _ustr );
getPropertyValue( nRed, xPropSet, u"AdjustRed" _ustr );
getPropertyValue( nGreen, xPropSet, u"AdjustGreen" _ustr );
getPropertyValue( nBlue, xPropSet, u"AdjustBlue" _ustr );
getPropertyValue( nGamma, xPropSet, u"Gamma" _ustr );
getPropertyValue( nTransparency, xPropSet, u"Transparency" _ustr );
getPropertyValue( nRotation, xPropSet, u"RotateAngle" _ustr );
GraphicAttr aGraphAttrs;
aGraphAttrs.SetDrawMode( static_cast <GraphicDrawMode>(eColorMode) );
aGraphAttrs.SetLuminance( nLuminance );
aGraphAttrs.SetContrast( nContrast );
aGraphAttrs.SetChannelR( nRed );
aGraphAttrs.SetChannelG( nGreen );
aGraphAttrs.SetChannelB( nBlue );
aGraphAttrs.SetGamma( nGamma );
aGraphAttrs.SetAlpha( 255 - static_cast <sal_uInt8>(nTransparency) );
aGraphAttrs.SetRotation( Degree10(static_cast <sal_Int16>(nRotation*10 )) );
text::GraphicCrop aGraphCrop;
if ( getPropertyValue( aGraphCrop, xPropSet, u"GraphicCrop" _ustr ))
{
aGraphAttrs.SetCrop( aGraphCrop.Left,
aGraphCrop.Top,
aGraphCrop.Right,
aGraphCrop.Bottom );
}
// fetch readily transformed and color-modified
// graphic
std::shared_ptr<Graphic> pGraphic
= ::std::make_shared<Graphic>(xGraphicObject->GetTransformedGraphic(
xGraphicObject->GetPrefSize(),
xGraphicObject->GetPrefMapMode(),
aGraphAttrs ) );
return DrawShape::create( xCurrShape,
xPage,
mnAscendingPrio,
std::move(pGraphic),
mrContext );
}
else
{
return DrawShape::create( xCurrShape,
xPage,
mnAscendingPrio,
false ,
mrContext );
}
}
bool ShapeImporter::isSkip(
uno::Reference<beans::XPropertySet> const & xPropSet,
std::u16string_view shapeType,
uno::Reference< drawing::XLayer> const & xLayer )
{
// skip empty presentation objects:
bool bEmpty = false ;
if ( getPropertyValue( bEmpty,
xPropSet,
u"IsEmptyPresentationObject" _ustr) &&
bEmpty )
{
// check object have fill or linestyle, if have, it should be visible
drawing::FillStyle aFillStyle{ drawing::FillStyle_NONE };
if (getPropertyValue(aFillStyle,
xPropSet, u"FillStyle" _ustr) &&
aFillStyle != drawing::FillStyle_NONE)
{
bEmpty = false ;
}
drawing::LineStyle aLineStyle{ drawing::LineStyle_NONE };
if (bEmpty && getPropertyValue(aLineStyle,
xPropSet, u"LineStyle" _ustr) &&
aLineStyle != drawing::LineStyle_NONE)
{
bEmpty = false ;
}
if (bEmpty)
return true ;
}
//skip shapes which corresponds to annotations
if (xLayer.is())
{
OUString layerName;
const uno::Any a(xLayer->getPropertyValue(u"Name" _ustr) );
bool const bRet = (a >>= layerName);
if (bRet)
{
if ( layerName == "DrawnInSlideshow" )
{
//Transform shapes into PolyPolygons
importPolygons(xPropSet);
return true ;
}
}
}
// don't export presentation placeholders on masterpage
// they can be non empty when user edits the default texts
if (mbConvertingMasterPage)
{
if ( shapeType == u"com.sun.star.presentation.TitleTextShape" || shapeType == u"com.sun.star.presentation.OutlinerShape" )
{
return true ;
}
if ( mbTextFieldsOnly )
{
if ( !( shapeType == u"com.sun.star.presentation.SlideNumberShape" ||
shapeType == u"com.sun.star.presentation.FooterShape" ||
shapeType == u"com.sun.star.presentation.DateTimeShape" ) )
{
return true ;
}
}
}
return false ;
}
void ShapeImporter::importPolygons(uno::Reference<beans::XPropertySet> const & xPropSet) {
drawing::PointSequenceSequence aRetval;
sal_Int32 nLineColor=0 ;
double fLineWidth;
getPropertyValue( aRetval, xPropSet, u"PolyPolygon" _ustr );
getPropertyValue( nLineColor, xPropSet, u"LineColor" _ustr );
getPropertyValue( fLineWidth, xPropSet, u"LineWidth" _ustr );
const drawing::PointSequence* pOuterSequence = aRetval.getArray();
::basegfx::B2DPolygon aPoly;
basegfx::B2DPoint aPoint;
for ( const awt::Point& rPoint : *pOuterSequence )
{
aPoint.setX(rPoint.X);
aPoint.setY(rPoint.Y);
aPoly.append( aPoint );
}
for ( const auto & pView : mrContext.mrViewContainer )
{
::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
::cppcanvas::BaseGfxFactory::createPolyPolygon( pView->getCanvas(),
aPoly ) );
if ( pPolyPoly )
{
pPolyPoly->setRGBALineColor( unoColor2RGBColor( nLineColor ).getIntegerColor() );
pPolyPoly->setStrokeWidth(fLineWidth);
pPolyPoly->draw();
pPolyPoly->setIsFromPreviousSlideshow(true );
maPolygons.push_back(pPolyPoly);
}
}
}
ShapeSharedPtr ShapeImporter::importBackgroundShape() // throw (ShapeLoadFailedException)
{
if ( maShapesStack.empty() )
throw ShapeLoadFailedException();
XShapesEntry& rTop = maShapesStack.top();
ShapeSharedPtr pBgShape(
createBackgroundShape(mxPage,
uno::Reference<drawing::XDrawPage>(
rTop.mxShapes,
uno::UNO_QUERY_THROW),
mrContext) );
mnAscendingPrio += 1 .0 ;
return pBgShape;
}
ShapeSharedPtr ShapeImporter::importShape() // throw (ShapeLoadFailedException)
{
ShapeSharedPtr pRet;
bool bIsGroupShape = false ;
while ( !maShapesStack.empty() && !pRet )
{
XShapesEntry& rTop = maShapesStack.top();
if ( rTop.mnPos < rTop.mnCount )
{
uno::Reference<drawing::XShape> const xCurrShape(
rTop.mxShapes->getByIndex( rTop.mnPos ), uno::UNO_QUERY );
++rTop.mnPos;
uno::Reference<beans::XPropertySet> xPropSet(
xCurrShape, uno::UNO_QUERY );
if ( !xPropSet.is() )
{
// we definitely need the properties of
// the shape here. This will also fail,
// if getByIndex did not return a valid
// shape
throw ShapeLoadFailedException();
}
//Retrieve the layer for the current shape
uno::Reference< drawing::XLayer > xDrawnInSlideshow;
uno::Reference< drawing::XLayerSupplier > xLayerSupplier(mxPagesSupplier, uno::UNO_QUERY);
if (xLayerSupplier.is())
{
uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
xDrawnInSlideshow = xLayerManager->getLayerForShape(xCurrShape);
}
OUString const shapeType( xCurrShape->getShapeType());
// is this shape presentation-invisible?
if ( !isSkip(xPropSet, shapeType, xDrawnInSlideshow) )
{
bIsGroupShape = shapeType == "com.sun.star.drawing.GroupShape" ;
if ( rTop.mpGroupShape ) // in group particle mode?
{
pRet = std::make_shared<ShapeOfGroup>(
rTop.mpGroupShape /* container shape */,
xCurrShape, xPropSet,
mnAscendingPrio );
}
else
{
pRet = createShape( xCurrShape, xPropSet, shapeType );
}
mnAscendingPrio += 1 .0 ;
}
}
if ( rTop.mnPos >= rTop.mnCount )
{
// group or top-level shapes finished:
maShapesStack.pop();
}
if ( bIsGroupShape && pRet )
{
// push new group on the stack: group traversal
maShapesStack.push( XShapesEntry( pRet ) );
}
}
return pRet;
}
bool ShapeImporter::isImportDone() const
{
return maShapesStack.empty();
}
const PolyPolygonVector& ShapeImporter::getPolygons() const
{
return maPolygons;
}
ShapeImporter::ShapeImporter( uno::Reference<drawing::XDrawPage> const & xPage,
uno::Reference<drawing::XDrawPage> xActualPage,
uno::Reference<drawing::XDrawPagesSupplier> xPagesSupplier,
const SlideShowContext& rContext,
sal_Int32 nOrdNumStart,
bool bConvertingMasterPage ) :
mxPage(std::move( xActualPage )),
mxPagesSupplier(std::move( xPagesSupplier )),
mrContext( rContext ),
maPolygons(),
maShapesStack(),
mnAscendingPrio( nOrdNumStart ),
mbConvertingMasterPage( bConvertingMasterPage ),
mbMasterPageObjectsOnly( false ),
mbTextFieldsOnly( false )
{
uno::Reference<drawing::XShapes> const xShapes(
xPage, uno::UNO_QUERY_THROW );
maShapesStack.push( XShapesEntry(xShapes) );
}
} // namespace presentation
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=92 H=94 G=92
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland
2026-10-10
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126438
#Domains=1897691