1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/GraphicObject.hxx>
22 #include <basegfx/point/b2dpoint.hxx>
23 #include <basegfx/polygon/b2dpolygon.hxx>
24 #include <cppcanvas/basegfxfactory.hxx>
25 #include <cppcanvas/polypolygon.hxx>
26 #include <com/sun/star/awt/Rectangle.hpp>
27 #include <com/sun/star/drawing/ColorMode.hpp>
28 #include <com/sun/star/text/GraphicCrop.hpp>
29 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
30 #include <com/sun/star/drawing/PointSequence.hpp>
31 #include <com/sun/star/drawing/XLayerSupplier.hpp>
32 #include <com/sun/star/drawing/XLayerManager.hpp>
33 #include <com/sun/star/graphic/XGraphic.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
37 #include "drawshape.hxx"
38 #include "backgroundshape.hxx"
39 #include "mediashape.hxx"
40 #include "appletshape.hxx"
41 #include <shapeimporter.hxx>
42 #include <slideshowexceptions.hxx>
44 #include <slideshowcontext.hxx>
45 #include <unoviewcontainer.hxx>
49 using namespace com::sun::star
;
51 namespace slideshow::internal
{
55 std::unique_ptr
<GraphicObject
> importShapeGraphic(uno::Reference
<beans::XPropertySet
> const& xPropSet
)
57 std::unique_ptr
<GraphicObject
> xRet
;
59 uno::Reference
<graphic::XGraphic
> xGraphic
;
60 if (!getPropertyValue(xGraphic
, xPropSet
, "Graphic") || !xGraphic
.is())
62 // no or empty property - cannot import shape graphic
66 Graphic
aGraphic(xGraphic
);
67 xRet
.reset(new GraphicObject(std::move(aGraphic
)));
69 if (GraphicType::Default
== xRet
->GetType() || GraphicType::NONE
== xRet
->GetType())
76 /** This shape implementation just acts as a dummy for the layermanager.
77 Its sole role is for hit test detection of group shapes.
79 class ShapeOfGroup
: public Shape
82 ShapeOfGroup( ShapeSharedPtr
const& pGroupShape
,
83 uno::Reference
<drawing::XShape
> xShape
,
84 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
88 virtual uno::Reference
<drawing::XShape
> getXShape() const override
;
89 virtual void addViewLayer( ViewLayerSharedPtr
const& pNewLayer
,
90 bool bRedrawLayer
) override
;
91 virtual bool removeViewLayer( ViewLayerSharedPtr
const& pNewLayer
) override
;
92 virtual void clearAllViewLayers() override
;
93 virtual bool update() const override
;
94 virtual bool render() const override
;
95 virtual bool isContentChanged() const override
;
96 virtual basegfx::B2DRectangle
getBounds() const override
;
97 virtual basegfx::B2DRectangle
getDomBounds() const override
;
98 virtual basegfx::B2DRectangle
getUpdateArea() const override
;
99 virtual bool isVisible() const override
;
100 virtual double getPriority() const override
;
101 virtual bool isBackgroundDetached() const override
;
104 ShapeSharedPtr
const mpGroupShape
;
105 uno::Reference
<drawing::XShape
> const mxShape
;
107 basegfx::B2DPoint maPosOffset
;
112 ShapeOfGroup::ShapeOfGroup( ShapeSharedPtr
const& pGroupShape
,
113 uno::Reference
<drawing::XShape
> xShape
,
114 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
116 mpGroupShape(pGroupShape
),
117 mxShape(std::move(xShape
)),
121 uno::Any
const aTmpRect_( xPropSet
->getPropertyValue( "BoundRect" ));
122 awt::Rectangle
const aTmpRect( aTmpRect_
.get
<awt::Rectangle
>() );
123 basegfx::B2DRectangle
const groupPosSize( pGroupShape
->getBounds() );
124 maPosOffset
= basegfx::B2DPoint( aTmpRect
.X
- groupPosSize
.getMinX(),
125 aTmpRect
.Y
- groupPosSize
.getMinY() );
126 mnWidth
= aTmpRect
.Width
;
127 mnHeight
= aTmpRect
.Height
;
130 uno::Reference
<drawing::XShape
> ShapeOfGroup::getXShape() const
135 void ShapeOfGroup::addViewLayer( ViewLayerSharedPtr
const& /*pNewLayer*/,
136 bool /*bRedrawLayer*/ )
140 bool ShapeOfGroup::removeViewLayer( ViewLayerSharedPtr
const& /*pNewLayer*/ )
145 void ShapeOfGroup::clearAllViewLayers()
149 bool ShapeOfGroup::update() const
154 bool ShapeOfGroup::render() const
159 bool ShapeOfGroup::isContentChanged() const
164 basegfx::B2DRectangle
ShapeOfGroup::getBounds() const
166 basegfx::B2DRectangle
const groupPosSize( mpGroupShape
->getBounds() );
167 double const posX
= groupPosSize
.getMinX() + maPosOffset
.getX();
168 double const posY
= groupPosSize
.getMinY() + maPosOffset
.getY();
169 return basegfx::B2DRectangle( posX
, posY
, posX
+ mnWidth
, posY
+ mnHeight
);
172 basegfx::B2DRectangle
ShapeOfGroup::getDomBounds() const
177 basegfx::B2DRectangle
ShapeOfGroup::getUpdateArea() const
182 bool ShapeOfGroup::isVisible() const
184 return mpGroupShape
->isVisible();
187 double ShapeOfGroup::getPriority() const
192 bool ShapeOfGroup::isBackgroundDetached() const
199 ShapeSharedPtr
ShapeImporter::createShape(
200 uno::Reference
<drawing::XShape
> const& xCurrShape
,
201 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
202 std::u16string_view shapeType
) const
204 if( shapeType
== u
"com.sun.star.drawing.MediaShape" || shapeType
== u
"com.sun.star.presentation.MediaShape" )
206 // Media shape (video etc.). This is a special object
207 return createMediaShape(xCurrShape
,
211 else if( shapeType
== u
"com.sun.star.drawing.AppletShape" )
213 // PropertyValues to copy from XShape to applet
214 static const char* aPropertyValues
[] =
223 // (Java)Applet shape. This is a special object
224 return createAppletShape( xCurrShape
,
226 "com.sun.star.comp.sfx2.AppletObject",
228 SAL_N_ELEMENTS(aPropertyValues
),
231 else if( shapeType
== u
"com.sun.star.drawing.OLE2Shape" || shapeType
== u
"com.sun.star.presentation.OLE2Shape" )
233 // #i46224# Mark OLE shapes as foreign content - scan them for
234 // unsupported actions, and fallback to bitmap, if necessary
235 return DrawShape::create( xCurrShape
,
241 else if( shapeType
== u
"com.sun.star.drawing.GraphicObjectShape" || shapeType
== u
"com.sun.star.presentation.GraphicObjectShape" )
243 // to get hold of GIF animations, inspect Graphic
244 // objects more thoroughly (the plain-jane shape
245 // metafile of course would only contain the first
247 std::unique_ptr
<GraphicObject
> xGraphicObject(importShapeGraphic(xPropSet
));
249 return ShapeSharedPtr(); // error loading graphic -
250 // no placeholders in
253 if (!xGraphicObject
->IsAnimated())
255 // no animation - simply utilize plain draw shape import
257 // import shape as bitmap - either it's a bitmap
258 // anyway, or it's a metafile, which currently the
259 // metafile renderer might not display correctly.
260 return DrawShape::create( xCurrShape
,
268 // now extract relevant shape attributes via API
271 drawing::ColorMode
eColorMode( drawing::ColorMode_STANDARD
);
272 sal_Int16
nLuminance(0);
273 sal_Int16
nContrast(0);
278 sal_Int16
nTransparency(0);
279 sal_Int32
nRotation(0);
281 getPropertyValue( eColorMode
, xPropSet
, "GraphicColorMode" );
282 getPropertyValue( nLuminance
, xPropSet
, "AdjustLuminance" );
283 getPropertyValue( nContrast
, xPropSet
, "AdjustContrast" );
284 getPropertyValue( nRed
, xPropSet
, "AdjustRed" );
285 getPropertyValue( nGreen
, xPropSet
, "AdjustGreen" );
286 getPropertyValue( nBlue
, xPropSet
, "AdjustBlue" );
287 getPropertyValue( nGamma
, xPropSet
, "Gamma" );
288 getPropertyValue( nTransparency
, xPropSet
, "Transparency" );
289 getPropertyValue( nRotation
, xPropSet
, "RotateAngle" );
291 GraphicAttr aGraphAttrs
;
292 aGraphAttrs
.SetDrawMode( static_cast<GraphicDrawMode
>(eColorMode
) );
293 aGraphAttrs
.SetLuminance( nLuminance
);
294 aGraphAttrs
.SetContrast( nContrast
);
295 aGraphAttrs
.SetChannelR( nRed
);
296 aGraphAttrs
.SetChannelG( nGreen
);
297 aGraphAttrs
.SetChannelB( nBlue
);
298 aGraphAttrs
.SetGamma( nGamma
);
299 aGraphAttrs
.SetAlpha( 255 - static_cast<sal_uInt8
>(nTransparency
) );
300 aGraphAttrs
.SetRotation( Degree10(static_cast<sal_Int16
>(nRotation
*10)) );
302 text::GraphicCrop aGraphCrop
;
303 if( getPropertyValue( aGraphCrop
, xPropSet
, "GraphicCrop" ))
305 aGraphAttrs
.SetCrop( aGraphCrop
.Left
,
311 // fetch readily transformed and color-modified
316 xGraphicObject
->GetTransformedGraphic(
317 xGraphicObject
->GetPrefSize(),
318 xGraphicObject
->GetPrefMapMode(),
321 return DrawShape::create( xCurrShape
,
329 return DrawShape::create( xCurrShape
,
337 bool ShapeImporter::isSkip(
338 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
339 std::u16string_view shapeType
,
340 uno::Reference
< drawing::XLayer
> const& xLayer
)
342 // skip empty presentation objects:
344 if( getPropertyValue( bEmpty
,
346 "IsEmptyPresentationObject") &&
352 //skip shapes which corresponds to annotations
356 const uno::Any
& a(xLayer
->getPropertyValue("Name") );
357 bool const bRet
= (a
>>= layerName
);
360 if( layerName
== "DrawnInSlideshow" )
362 //Transform shapes into PolyPolygons
363 importPolygons(xPropSet
);
370 // don't export presentation placeholders on masterpage
371 // they can be non empty when user edits the default texts
372 if(mbConvertingMasterPage
)
374 if( shapeType
== u
"com.sun.star.presentation.TitleTextShape" || shapeType
== u
"com.sun.star.presentation.OutlinerShape" )
383 void ShapeImporter::importPolygons(uno::Reference
<beans::XPropertySet
> const& xPropSet
) {
385 drawing::PointSequenceSequence aRetval
;
386 sal_Int32 nLineColor
=0;
388 getPropertyValue( aRetval
, xPropSet
, "PolyPolygon" );
389 getPropertyValue( nLineColor
, xPropSet
, "LineColor" );
390 getPropertyValue( fLineWidth
, xPropSet
, "LineWidth" );
392 const drawing::PointSequence
* pOuterSequence
= aRetval
.getArray();
394 ::basegfx::B2DPolygon aPoly
;
395 basegfx::B2DPoint aPoint
;
396 for( const awt::Point
& rPoint
: *pOuterSequence
)
398 aPoint
.setX(rPoint
.X
);
399 aPoint
.setY(rPoint
.Y
);
400 aPoly
.append( aPoint
);
402 for( const auto& pView
: mrContext
.mrViewContainer
)
404 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly(
405 ::cppcanvas::BaseGfxFactory::createPolyPolygon( pView
->getCanvas(),
409 pPolyPoly
->setRGBALineColor( unoColor2RGBColor( nLineColor
).getIntegerColor() );
410 pPolyPoly
->setStrokeWidth(fLineWidth
);
412 maPolygons
.push_back(pPolyPoly
);
417 ShapeSharedPtr
ShapeImporter::importBackgroundShape() // throw (ShapeLoadFailedException)
419 if( maShapesStack
.empty() )
420 throw ShapeLoadFailedException();
422 XShapesEntry
& rTop
= maShapesStack
.top();
423 ShapeSharedPtr
pBgShape(
424 createBackgroundShape(mxPage
,
425 uno::Reference
<drawing::XDrawPage
>(
427 uno::UNO_QUERY_THROW
),
429 mnAscendingPrio
+= 1.0;
434 ShapeSharedPtr
ShapeImporter::importShape() // throw (ShapeLoadFailedException)
437 bool bIsGroupShape
= false;
439 while( !maShapesStack
.empty() && !pRet
)
441 XShapesEntry
& rTop
= maShapesStack
.top();
442 if( rTop
.mnPos
< rTop
.mnCount
)
444 uno::Reference
<drawing::XShape
> const xCurrShape(
445 rTop
.mxShapes
->getByIndex( rTop
.mnPos
), uno::UNO_QUERY
);
447 uno::Reference
<beans::XPropertySet
> xPropSet(
448 xCurrShape
, uno::UNO_QUERY
);
451 // we definitely need the properties of
452 // the shape here. This will also fail,
453 // if getByIndex did not return a valid
455 throw ShapeLoadFailedException();
458 //Retrieve the layer for the current shape
459 uno::Reference
< drawing::XLayer
> xDrawnInSlideshow
;
461 uno::Reference
< drawing::XLayerSupplier
> xLayerSupplier(mxPagesSupplier
, uno::UNO_QUERY
);
462 if(xLayerSupplier
.is())
464 uno::Reference
< container::XNameAccess
> xNameAccess
= xLayerSupplier
->getLayerManager();
466 uno::Reference
< drawing::XLayerManager
> xLayerManager(xNameAccess
, uno::UNO_QUERY
);
468 xDrawnInSlideshow
= xLayerManager
->getLayerForShape(xCurrShape
);
471 OUString
const shapeType( xCurrShape
->getShapeType());
473 // is this shape presentation-invisible?
474 if( !isSkip(xPropSet
, shapeType
, xDrawnInSlideshow
) )
476 bIsGroupShape
= shapeType
== "com.sun.star.drawing.GroupShape";
478 if( rTop
.mpGroupShape
) // in group particle mode?
480 pRet
= std::make_shared
<ShapeOfGroup
>(
481 rTop
.mpGroupShape
/* container shape */,
482 xCurrShape
, xPropSet
,
487 pRet
= createShape( xCurrShape
, xPropSet
, shapeType
);
489 mnAscendingPrio
+= 1.0;
492 if( rTop
.mnPos
>= rTop
.mnCount
)
494 // group or top-level shapes finished:
497 if( bIsGroupShape
&& pRet
)
499 // push new group on the stack: group traversal
500 maShapesStack
.push( XShapesEntry( pRet
) );
507 bool ShapeImporter::isImportDone() const
509 return maShapesStack
.empty();
512 const PolyPolygonVector
& ShapeImporter::getPolygons() const
517 ShapeImporter::ShapeImporter( uno::Reference
<drawing::XDrawPage
> const& xPage
,
518 uno::Reference
<drawing::XDrawPage
> xActualPage
,
519 uno::Reference
<drawing::XDrawPagesSupplier
> xPagesSupplier
,
520 const SlideShowContext
& rContext
,
521 sal_Int32 nOrdNumStart
,
522 bool bConvertingMasterPage
) :
523 mxPage(std::move( xActualPage
)),
524 mxPagesSupplier(std::move( xPagesSupplier
)),
525 mrContext( rContext
),
528 mnAscendingPrio( nOrdNumStart
),
529 mbConvertingMasterPage( bConvertingMasterPage
)
531 uno::Reference
<drawing::XShapes
> const xShapes(
532 xPage
, uno::UNO_QUERY_THROW
);
533 maShapesStack
.push( XShapesEntry(xShapes
) );
536 } // namespace presentation
538 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */