LibreOffice Module slideshow (master) 1
shapeimporter.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <utility>
21#include <vcl/GraphicObject.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>
36
37#include "drawshape.hxx"
38#include "backgroundshape.hxx"
39#include "mediashape.hxx"
40#include "appletshape.hxx"
41#include <shapeimporter.hxx>
43#include <tools.hxx>
44#include <slideshowcontext.hxx>
45#include <unoviewcontainer.hxx>
46
47#include <memory>
48
49using namespace com::sun::star;
50
51namespace slideshow::internal {
52
53namespace {
54
55std::unique_ptr<GraphicObject> importShapeGraphic(uno::Reference<beans::XPropertySet> const& xPropSet)
56{
57 std::unique_ptr<GraphicObject> xRet;
58
59 uno::Reference<graphic::XGraphic> xGraphic;
60 if (!getPropertyValue(xGraphic, xPropSet, "Graphic") || !xGraphic.is())
61 {
62 // no or empty property - cannot import shape graphic
63 return xRet;
64 }
65
66 Graphic aGraphic(xGraphic);
67 xRet.reset(new GraphicObject(std::move(aGraphic)));
68
69 if (GraphicType::Default == xRet->GetType() || GraphicType::NONE == xRet->GetType())
70 {
71 xRet.reset();
72 }
73 return xRet;
74}
75
79class ShapeOfGroup : public Shape
80{
81public:
82 ShapeOfGroup( ShapeSharedPtr const& pGroupShape,
83 uno::Reference<drawing::XShape> xShape,
84 uno::Reference<beans::XPropertySet> const& xPropSet,
85 double nPrio );
86
87 // Shape:
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;
102
103private:
105 uno::Reference<drawing::XShape> const mxShape;
106 double const mnPrio;
108 double mnWidth;
109 double mnHeight;
110};
111
112ShapeOfGroup::ShapeOfGroup( ShapeSharedPtr const& pGroupShape,
113 uno::Reference<drawing::XShape> xShape,
114 uno::Reference<beans::XPropertySet> const& xPropSet,
115 double nPrio ) :
116 mpGroupShape(pGroupShape),
117 mxShape(std::move(xShape)),
118 mnPrio(nPrio)
119{
120 // read bound rect
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;
128}
129
130uno::Reference<drawing::XShape> ShapeOfGroup::getXShape() const
131{
132 return mxShape;
133}
134
135void ShapeOfGroup::addViewLayer( ViewLayerSharedPtr const& /*pNewLayer*/,
136 bool /*bRedrawLayer*/ )
137{
138}
139
140bool ShapeOfGroup::removeViewLayer( ViewLayerSharedPtr const& /*pNewLayer*/ )
141{
142 return true;
143}
144
145void ShapeOfGroup::clearAllViewLayers()
146{
147}
148
149bool ShapeOfGroup::update() const
150{
151 return true;
152}
153
154bool ShapeOfGroup::render() const
155{
156 return true;
157}
158
159bool ShapeOfGroup::isContentChanged() const
160{
161 return false;
162}
163
164basegfx::B2DRectangle ShapeOfGroup::getBounds() const
165{
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 );
170}
171
172basegfx::B2DRectangle ShapeOfGroup::getDomBounds() const
173{
174 return getBounds();
175}
176
177basegfx::B2DRectangle ShapeOfGroup::getUpdateArea() const
178{
179 return getBounds();
180}
181
182bool ShapeOfGroup::isVisible() const
183{
184 return mpGroupShape->isVisible();
185}
186
187double ShapeOfGroup::getPriority() const
188{
189 return mnPrio;
190}
191
192bool ShapeOfGroup::isBackgroundDetached() const
193{
194 return false;
195}
196
197} // anon namespace
198
199ShapeSharedPtr ShapeImporter::createShape(
200 uno::Reference<drawing::XShape> const& xCurrShape,
202 std::u16string_view shapeType ) const
203{
204 if( shapeType == u"com.sun.star.drawing.MediaShape" || shapeType == u"com.sun.star.presentation.MediaShape" )
205 {
206 // Media shape (video etc.). This is a special object
207 return createMediaShape(xCurrShape,
208 mnAscendingPrio,
209 mrContext);
210 }
211 else if( shapeType == u"com.sun.star.drawing.AppletShape" )
212 {
213 // PropertyValues to copy from XShape to applet
214 static const char* aPropertyValues[] =
215 {
216 "AppletCodeBase",
217 "AppletName",
218 "AppletCode",
219 "AppletCommands",
220 "AppletIsScript"
221 };
222
223 // (Java)Applet shape. This is a special object
224 return createAppletShape( xCurrShape,
225 mnAscendingPrio,
226 "com.sun.star.comp.sfx2.AppletObject",
229 mrContext );
230 }
231 else if( shapeType == u"com.sun.star.drawing.OLE2Shape" || shapeType == u"com.sun.star.presentation.OLE2Shape" )
232 {
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,
236 mxPage,
237 mnAscendingPrio,
238 true,
239 mrContext );
240 }
241 else if( shapeType == u"com.sun.star.drawing.GraphicObjectShape" || shapeType == u"com.sun.star.presentation.GraphicObjectShape" )
242 {
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
246 // animation frame)
247 std::unique_ptr<GraphicObject> xGraphicObject(importShapeGraphic(xPropSet));
248 if (!xGraphicObject)
249 return ShapeSharedPtr(); // error loading graphic -
250 // no placeholders in
251 // slideshow
252
253 if (!xGraphicObject->IsAnimated())
254 {
255 // no animation - simply utilize plain draw shape import
256
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,
261 mxPage,
262 mnAscendingPrio,
263 true,
264 mrContext );
265 }
266
267
268 // now extract relevant shape attributes via API
269
270
271 drawing::ColorMode eColorMode( drawing::ColorMode_STANDARD );
272 sal_Int16 nLuminance(0);
273 sal_Int16 nContrast(0);
274 sal_Int16 nRed(0);
275 sal_Int16 nGreen(0);
276 sal_Int16 nBlue(0);
277 double nGamma(1.0);
278 sal_Int16 nTransparency(0);
279 sal_Int32 nRotation(0);
280
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" );
290
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)) );
301
302 text::GraphicCrop aGraphCrop;
303 if( getPropertyValue( aGraphCrop, xPropSet, "GraphicCrop" ))
304 {
305 aGraphAttrs.SetCrop( aGraphCrop.Left,
306 aGraphCrop.Top,
307 aGraphCrop.Right,
308 aGraphCrop.Bottom );
309 }
310
311 // fetch readily transformed and color-modified
312 // graphic
313
314
315 Graphic aGraphic(
316 xGraphicObject->GetTransformedGraphic(
317 xGraphicObject->GetPrefSize(),
318 xGraphicObject->GetPrefMapMode(),
319 aGraphAttrs ) );
320
321 return DrawShape::create( xCurrShape,
322 mxPage,
323 mnAscendingPrio,
324 aGraphic,
325 mrContext );
326 }
327 else
328 {
329 return DrawShape::create( xCurrShape,
330 mxPage,
331 mnAscendingPrio,
332 false,
333 mrContext );
334 }
335}
336
337bool ShapeImporter::isSkip(
339 std::u16string_view shapeType,
341{
342 // skip empty presentation objects:
343 bool bEmpty = false;
344 if( getPropertyValue( bEmpty,
345 xPropSet,
346 "IsEmptyPresentationObject") &&
347 bEmpty )
348 {
349 return true;
350 }
351
352 //skip shapes which corresponds to annotations
353 if(xLayer.is())
354 {
355 OUString layerName;
356 const uno::Any& a(xLayer->getPropertyValue("Name") );
357 bool const bRet = (a >>= layerName);
358 if(bRet)
359 {
360 if( layerName == "DrawnInSlideshow" )
361 {
362 //Transform shapes into PolyPolygons
363 importPolygons(xPropSet);
364
365 return true;
366 }
367 }
368 }
369
370 // don't export presentation placeholders on masterpage
371 // they can be non empty when user edits the default texts
372 if(mbConvertingMasterPage)
373 {
374 if( shapeType == u"com.sun.star.presentation.TitleTextShape" || shapeType == u"com.sun.star.presentation.OutlinerShape" )
375 {
376 return true;
377 }
378 }
379 return false;
380}
381
382
383void ShapeImporter::importPolygons(uno::Reference<beans::XPropertySet> const& xPropSet) {
384
385 drawing::PointSequenceSequence aRetval;
386 sal_Int32 nLineColor=0;
387 double fLineWidth;
388 getPropertyValue( aRetval, xPropSet, "PolyPolygon" );
389 getPropertyValue( nLineColor, xPropSet, "LineColor" );
390 getPropertyValue( fLineWidth, xPropSet, "LineWidth" );
391
392 const drawing::PointSequence* pOuterSequence = aRetval.getArray();
393
395 basegfx::B2DPoint aPoint;
396 for( const awt::Point& rPoint : *pOuterSequence )
397 {
398 aPoint.setX(rPoint.X);
399 aPoint.setY(rPoint.Y);
400 aPoly.append( aPoint );
401 }
402 for( const auto& pView : mrContext.mrViewContainer )
403 {
406 aPoly ) );
407 if( pPolyPoly )
408 {
409 pPolyPoly->setRGBALineColor( unoColor2RGBColor( nLineColor ).getIntegerColor() );
410 pPolyPoly->setStrokeWidth(fLineWidth);
411 pPolyPoly->draw();
412 maPolygons.push_back(pPolyPoly);
413 }
414 }
415}
416
417ShapeSharedPtr ShapeImporter::importBackgroundShape() // throw (ShapeLoadFailedException)
418{
419 if( maShapesStack.empty() )
421
422 XShapesEntry& rTop = maShapesStack.top();
423 ShapeSharedPtr pBgShape(
426 rTop.mxShapes,
427 uno::UNO_QUERY_THROW),
428 mrContext) );
429 mnAscendingPrio += 1.0;
430
431 return pBgShape;
432}
433
434ShapeSharedPtr ShapeImporter::importShape() // throw (ShapeLoadFailedException)
435{
436 ShapeSharedPtr pRet;
437 bool bIsGroupShape = false;
438
439 while( !maShapesStack.empty() && !pRet )
440 {
441 XShapesEntry& rTop = maShapesStack.top();
442 if( rTop.mnPos < rTop.mnCount )
443 {
444 uno::Reference<drawing::XShape> const xCurrShape(
445 rTop.mxShapes->getByIndex( rTop.mnPos ), uno::UNO_QUERY );
446 ++rTop.mnPos;
448 xCurrShape, uno::UNO_QUERY );
449 if( !xPropSet.is() )
450 {
451 // we definitely need the properties of
452 // the shape here. This will also fail,
453 // if getByIndex did not return a valid
454 // shape
456 }
457
458 //Retrieve the layer for the current shape
459 uno::Reference< drawing::XLayer > xDrawnInSlideshow;
460
461 uno::Reference< drawing::XLayerSupplier > xLayerSupplier(mxPagesSupplier, uno::UNO_QUERY);
462 if(xLayerSupplier.is())
463 {
464 uno::Reference< container::XNameAccess > xNameAccess = xLayerSupplier->getLayerManager();
465
466 uno::Reference< drawing::XLayerManager > xLayerManager(xNameAccess, uno::UNO_QUERY);
467
468 xDrawnInSlideshow = xLayerManager->getLayerForShape(xCurrShape);
469 }
470
471 OUString const shapeType( xCurrShape->getShapeType());
472
473 // is this shape presentation-invisible?
474 if( !isSkip(xPropSet, shapeType, xDrawnInSlideshow) )
475 {
476 bIsGroupShape = shapeType == "com.sun.star.drawing.GroupShape";
477
478 if( rTop.mpGroupShape ) // in group particle mode?
479 {
480 pRet = std::make_shared<ShapeOfGroup>(
481 rTop.mpGroupShape /* container shape */,
482 xCurrShape, xPropSet,
483 mnAscendingPrio );
484 }
485 else
486 {
487 pRet = createShape( xCurrShape, xPropSet, shapeType );
488 }
489 mnAscendingPrio += 1.0;
490 }
491 }
492 if( rTop.mnPos >= rTop.mnCount )
493 {
494 // group or top-level shapes finished:
495 maShapesStack.pop();
496 }
497 if( bIsGroupShape && pRet )
498 {
499 // push new group on the stack: group traversal
500 maShapesStack.push( XShapesEntry( pRet ) );
501 }
502 }
503
504 return pRet;
505}
506
507bool ShapeImporter::isImportDone() const
508{
509 return maShapesStack.empty();
510}
511
512const PolyPolygonVector& ShapeImporter::getPolygons() const
513{
514 return maPolygons;
515}
516
517ShapeImporter::ShapeImporter( uno::Reference<drawing::XDrawPage> const& xPage,
520 const SlideShowContext& rContext,
521 sal_Int32 nOrdNumStart,
522 bool bConvertingMasterPage ) :
523 mxPage(std::move( xActualPage )),
524 mxPagesSupplier(std::move( xPagesSupplier )),
525 mrContext( rContext ),
526 maPolygons(),
527 maShapesStack(),
528 mnAscendingPrio( nOrdNumStart ),
529 mbConvertingMasterPage( bConvertingMasterPage )
530{
532 xPage, uno::UNO_QUERY_THROW );
533 maShapesStack.push( XShapesEntry(xShapes) );
534}
535
536} // namespace presentation
537
538/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
GraphicDrawMode
PropertyValueVector_t aPropertyValues
const NodeContext & mrContext
void SetGamma(double fGamma)
void SetRotation(Degree10 nRotate10)
void SetChannelR(short nChannelRPercent)
void SetContrast(short nContrastPercent)
void SetChannelB(short nChannelBPercent)
void SetCrop(tools::Long nLeft_100TH_MM, tools::Long nTop_100TH_MM, tools::Long nRight_100TH_MM, tools::Long nBottom_100TH_MM)
void SetDrawMode(GraphicDrawMode eDrawMode)
void SetLuminance(short nLuminancePercent)
void SetAlpha(sal_uInt8 cAlpha)
void SetChannelG(short nChannelGPercent)
void append(const basegfx::B2DPoint &rPoint, sal_uInt32 nCount)
TYPE getMinX() const
TYPE getMinY() const
TYPE getX() const
void setY(TYPE fY)
TYPE getY() const
void setX(TYPE fX)
static PolyPolygonSharedPtr createPolyPolygon(const CanvasSharedPtr &, const ::basegfx::B2DPolygon &rPoly)
::std::stack< XShapesEntry > maShapesStack
float u
uno_Any a
#define SAL_N_ELEMENTS(arr)
css::uno::Reference< css::drawing::XShape > OOO_DLLPUBLIC_TEST createShape(const css::uno::Reference< css::lang::XComponent > &r_xComponent, std::u16string_view r_aKind, const sal_Int32 nX, const sal_Int32 nY, const sal_Int32 nWidth, const sal_Int32 nHeight)
B2DRange B2DRectangle
std::shared_ptr< PolyPolygon > PolyPolygonSharedPtr
::std::vector< ::cppcanvas::PolyPolygonSharedPtr > PolyPolygonVector
ShapeSharedPtr createMediaShape(const uno::Reference< drawing::XShape > &xShape, double nPrio, const SlideShowContext &rContext)
Definition: mediashape.cxx:247
bool getPropertyValue(ValueType &rValue, css::uno::Reference< css::beans::XPropertySet > const &xPropSet, OUString const &propName)
Definition: tools.hxx:278
std::shared_ptr< ViewLayer > ViewLayerSharedPtr
Definition: viewlayer.hxx:168
ShapeSharedPtr createBackgroundShape(const uno::Reference< drawing::XDrawPage > &xDrawPage, const uno::Reference< drawing::XDrawPage > &xMasterPage, const SlideShowContext &rContext)
RGBColor unoColor2RGBColor(sal_Int32)
Convert a plain UNO API 32 bit int to RGBColor.
Definition: tools.cxx:634
::std::shared_ptr< Shape > ShapeSharedPtr
std::shared_ptr< Shape > createAppletShape(const uno::Reference< drawing::XShape > &xShape, double nPrio, const OUString &rServiceName, const char **pPropCopyTable, std::size_t nNumPropEntries, const SlideShowContext &rContext)
double const mnPrio
uno::Reference< drawing::XShape > const mxShape
double mnWidth
basegfx::B2DPoint maPosOffset
double mnHeight
ShapeSharedPtr const mpGroupShape
PolyPolygonVector maPolygons
Definition: slideimpl.cxx:210
This exception is thrown, when the Shape class was not able to convert an API object into our interna...
css::uno::Reference< css::drawing::XShapes > const mxShapes
Common arguments for slideshow objects.
Shape
unsigned char sal_uInt8
bool update()