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 <canvas/debug.hxx>
22 #include <vcl/cvtgrf.hxx>
23 #include <tools/urlobj.hxx>
24 #include <tools/stream.hxx>
25 #include <svtools/grfmgr.hxx>
26 #include <unotools/ucbstreamhelper.hxx>
27 #include <unotools/streamwrap.hxx>
28 #include <basegfx/point/b2dpoint.hxx>
29 #include <basegfx/polygon/b2dpolygon.hxx>
30 #include <cppcanvas/basegfxfactory.hxx>
31 #include <cppcanvas/polypolygon.hxx>
32 #include <com/sun/star/awt/Rectangle.hpp>
33 #include <com/sun/star/drawing/ColorMode.hpp>
34 #include <com/sun/star/text/GraphicCrop.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
37 #include <com/sun/star/drawing/PointSequence.hpp>
38 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
39 #include <com/sun/star/drawing/XLayerSupplier.hpp>
40 #include <com/sun/star/drawing/XLayerManager.hpp>
41 #include <com/sun/star/container/XNameAccess.hpp>
42 #include <com/sun/star/lang/XComponent.hpp>
43 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
45 #include "drawshapesubsetting.hxx"
46 #include "drawshape.hxx"
47 #include "backgroundshape.hxx"
48 #include "mediashape.hxx"
49 #include "appletshape.hxx"
50 #include "shapeimporter.hxx"
51 #include "slideshowexceptions.hxx"
52 #include "gdimtftools.hxx"
54 #include "slideshowcontext.hxx"
56 #include <boost/shared_ptr.hpp>
57 #include <boost/scoped_ptr.hpp>
59 using namespace com::sun::star
;
66 bool importShapeGraphic(
67 GraphicObject
& o_rGraphic
,
68 uno::Reference
<beans::XPropertySet
> const& xPropSet
)
71 if( !getPropertyValue( aURL
, xPropSet
, "GraphicURL") ||
74 // no or empty property - cannot import shape graphic
78 OUString
const aVndUrl(
79 "vnd.sun.star.GraphicObject:" );
80 sal_Int32
nIndex( aURL
.indexOf( aVndUrl
) );
84 // skip past the end of the "vnd..." prefix
85 nIndex
+= aVndUrl
.getLength();
87 if(nIndex
>= aURL
.getLength())
89 OSL_FAIL( "ShapeImporter::importShape(): "
90 "embedded graphic has no graphic ID" );
94 // unique ID string found in URL, extract
96 OUString
const aUniqueId(
97 aURL
.copy( nIndex
, aURL
.getLength() - nIndex
) );
99 // TODO(T2): Creating a GraphicObject is not
100 // thread safe (internally calls VCL, and has
101 // unguarded internal singleton mpGlobalMgr)
103 // fetch already loaded graphic from graphic manager.
104 OString
const aOldString(OUStringToOString(aUniqueId
,
105 RTL_TEXTENCODING_UTF8
));
106 o_rGraphic
= GraphicObject( aOldString
);
109 if( GRAPHIC_DEFAULT
== o_rGraphic
.GetType()
110 || GRAPHIC_NONE
== o_rGraphic
.GetType() )
112 // even the GrfMgr does not seem to know this graphic
118 // no special string found, graphic must be
119 // external. Load via GraphicIm porter
120 INetURLObject
aTmp( aURL
);
121 boost::scoped_ptr
<SvStream
> pGraphicStream(
122 utl::UcbStreamHelper::CreateStream(
123 aTmp
.GetMainURL( INetURLObject::NO_DECODE
),
124 StreamMode::READ
) );
125 if( !pGraphicStream
)
127 OSL_FAIL( "ShapeImporter::importShape(): "
128 "cannot create input stream for graphic" );
133 if( GraphicConverter::Import(
134 *pGraphicStream
, aTmpGraphic
) != ERRCODE_NONE
)
136 OSL_FAIL( "ShapeImporter::importShape(): "
137 "Failed to import shape graphic from given URL" );
141 o_rGraphic
= GraphicObject( aTmpGraphic
);
146 /** This shape implementation just acts as a dummy for the layermanager.
147 Its sole role is for hit test detection of group shapes.
149 class ShapeOfGroup
: public Shape
152 ShapeOfGroup( ShapeSharedPtr
const& pGroupShape
,
153 uno::Reference
<drawing::XShape
> const& xShape
,
154 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
158 virtual uno::Reference
<drawing::XShape
> getXShape() const SAL_OVERRIDE
;
159 virtual void addViewLayer( ViewLayerSharedPtr
const& pNewLayer
,
160 bool bRedrawLayer
) SAL_OVERRIDE
;
161 virtual bool removeViewLayer( ViewLayerSharedPtr
const& pNewLayer
) SAL_OVERRIDE
;
162 virtual bool clearAllViewLayers() SAL_OVERRIDE
;
163 virtual bool update() const SAL_OVERRIDE
;
164 virtual bool render() const SAL_OVERRIDE
;
165 virtual bool isContentChanged() const SAL_OVERRIDE
;
166 virtual basegfx::B2DRectangle
getBounds() const SAL_OVERRIDE
;
167 virtual basegfx::B2DRectangle
getDomBounds() const SAL_OVERRIDE
;
168 virtual basegfx::B2DRectangle
getUpdateArea() const SAL_OVERRIDE
;
169 virtual bool isVisible() const SAL_OVERRIDE
;
170 virtual double getPriority() const SAL_OVERRIDE
;
171 virtual bool isBackgroundDetached() const SAL_OVERRIDE
;
174 ShapeSharedPtr
const mpGroupShape
;
175 uno::Reference
<drawing::XShape
> const mxShape
;
177 basegfx::B2DPoint maPosOffset
;
182 ShapeOfGroup::ShapeOfGroup( ShapeSharedPtr
const& pGroupShape
,
183 uno::Reference
<drawing::XShape
> const& xShape
,
184 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
186 mpGroupShape(pGroupShape
),
191 uno::Any
const aTmpRect_( xPropSet
->getPropertyValue( "BoundRect" ));
192 awt::Rectangle
const aTmpRect( aTmpRect_
.get
<awt::Rectangle
>() );
193 basegfx::B2DRectangle
const groupPosSize( pGroupShape
->getBounds() );
194 maPosOffset
= basegfx::B2DPoint( aTmpRect
.X
- groupPosSize
.getMinX(),
195 aTmpRect
.Y
- groupPosSize
.getMinY() );
196 mnWidth
= aTmpRect
.Width
;
197 mnHeight
= aTmpRect
.Height
;
200 uno::Reference
<drawing::XShape
> ShapeOfGroup::getXShape() const
205 void ShapeOfGroup::addViewLayer( ViewLayerSharedPtr
const& /*pNewLayer*/,
206 bool /*bRedrawLayer*/ )
210 bool ShapeOfGroup::removeViewLayer( ViewLayerSharedPtr
const& /*pNewLayer*/ )
215 bool ShapeOfGroup::clearAllViewLayers()
220 bool ShapeOfGroup::update() const
225 bool ShapeOfGroup::render() const
230 bool ShapeOfGroup::isContentChanged() const
235 basegfx::B2DRectangle
ShapeOfGroup::getBounds() const
237 basegfx::B2DRectangle
const groupPosSize( mpGroupShape
->getBounds() );
238 double const posX
= (groupPosSize
.getMinX() + maPosOffset
.getX());
239 double const posY
= (groupPosSize
.getMinY() + maPosOffset
.getY());
240 return basegfx::B2DRectangle( posX
, posY
, posX
+ mnWidth
, posY
+ mnHeight
);
243 basegfx::B2DRectangle
ShapeOfGroup::getDomBounds() const
248 basegfx::B2DRectangle
ShapeOfGroup::getUpdateArea() const
253 bool ShapeOfGroup::isVisible() const
255 return mpGroupShape
->isVisible();
258 double ShapeOfGroup::getPriority() const
263 bool ShapeOfGroup::isBackgroundDetached() const
270 ShapeSharedPtr
ShapeImporter::createShape(
271 uno::Reference
<drawing::XShape
> const& xCurrShape
,
272 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
273 OUString
const& shapeType
) const
275 if( shapeType
== "com.sun.star.drawing.MediaShape" || shapeType
== "com.sun.star.presentation.MediaShape" )
277 // Media shape (video etc.). This is a special object
278 return createMediaShape(xCurrShape
,
282 else if( shapeType
== "com.sun.star.drawing.PluginShape" )
284 // PropertyValues to copy from XShape to plugin
285 static const char* aPropertyValues
[] =
292 // (Netscape)Plugin shape. This is a special object
293 return createAppletShape( xCurrShape
,
295 OUString( "com.sun.star.comp.sfx2.PluginObject" ),
297 SAL_N_ELEMENTS(aPropertyValues
),
300 else if( shapeType
== "com.sun.star.drawing.AppletShape" )
302 // PropertyValues to copy from XShape to applet
303 static const char* aPropertyValues
[] =
312 // (Java)Applet shape. This is a special object
313 return createAppletShape( xCurrShape
,
315 OUString( "com.sun.star.comp.sfx2.AppletObject" ),
317 SAL_N_ELEMENTS(aPropertyValues
),
320 else if( shapeType
== "com.sun.star.drawing.OLE2Shape" || shapeType
== "com.sun.star.presentation.OLE2Shape" )
322 // #i46224# Mark OLE shapes as foreign content - scan them for
323 // unsupported actions, and fallback to bitmap, if necessary
324 return DrawShape::create( xCurrShape
,
330 else if( shapeType
== "com.sun.star.drawing.GraphicObjectShape" || shapeType
== "com.sun.star.presentation.GraphicObjectShape" )
332 GraphicObject aGraphicObject
;
334 // to get hold of GIF animations, inspect Graphic
335 // objects more thoroughly (the plain-jane shape
336 // metafile of course would only contain the first
338 if( !importShapeGraphic( aGraphicObject
, xPropSet
) )
339 return ShapeSharedPtr(); // error loading graphic -
340 // no placeholders in
343 if( !aGraphicObject
.IsAnimated() )
345 // no animation - simply utilize plain draw shape import
347 // import shape as bitmap - either it's a bitmap
348 // anyway, or it's a metafile, which currently the
349 // metafile renderer might not display correctly.
350 return DrawShape::create( xCurrShape
,
358 // now extract relevant shape attributes via API
361 drawing::ColorMode
eColorMode( drawing::ColorMode_STANDARD
);
362 sal_Int16
nLuminance(0);
363 sal_Int16
nContrast(0);
368 sal_Int16
nTransparency(0);
369 sal_Int32
nRotation(0);
371 getPropertyValue( eColorMode
, xPropSet
, "GraphicColorMode" );
372 getPropertyValue( nLuminance
, xPropSet
, "AdjustLuminance" );
373 getPropertyValue( nContrast
, xPropSet
, "AdjustContrast" );
374 getPropertyValue( nRed
, xPropSet
, "AdjustRed" );
375 getPropertyValue( nGreen
, xPropSet
, "AdjustGreen" );
376 getPropertyValue( nBlue
, xPropSet
, "AdjustBlue" );
377 getPropertyValue( nGamma
, xPropSet
, "Gamma" );
378 getPropertyValue( nTransparency
, xPropSet
, "Transparency" );
379 getPropertyValue( nRotation
, xPropSet
, "RotateAngle" );
381 GraphicAttr aGraphAttrs
;
382 aGraphAttrs
.SetDrawMode( (GraphicDrawMode
)eColorMode
);
383 aGraphAttrs
.SetLuminance( nLuminance
);
384 aGraphAttrs
.SetContrast( nContrast
);
385 aGraphAttrs
.SetChannelR( nRed
);
386 aGraphAttrs
.SetChannelG( nGreen
);
387 aGraphAttrs
.SetChannelB( nBlue
);
388 aGraphAttrs
.SetGamma( nGamma
);
389 aGraphAttrs
.SetTransparency( static_cast<sal_uInt8
>(nTransparency
) );
390 aGraphAttrs
.SetRotation( static_cast<sal_uInt16
>(nRotation
*10) );
392 text::GraphicCrop aGraphCrop
;
393 if( getPropertyValue( aGraphCrop
, xPropSet
, "GraphicCrop" ))
395 aGraphAttrs
.SetCrop( aGraphCrop
.Left
,
401 // fetch readily transformed and color-modified
406 aGraphicObject
.GetTransformedGraphic(
407 aGraphicObject
.GetPrefSize(),
408 aGraphicObject
.GetPrefMapMode(),
411 return DrawShape::create( xCurrShape
,
419 return DrawShape::create( xCurrShape
,
427 bool ShapeImporter::isSkip(
428 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
429 OUString
const& shapeType
,
430 uno::Reference
< drawing::XLayer
> const& xLayer
)
432 // skip empty presentation objects:
434 if( getPropertyValue( bEmpty
,
436 "IsEmptyPresentationObject") &&
442 //skip shapes which corresponds to annotations
446 uno::Reference
<beans::XPropertySet
> xPropLayerSet(
447 xLayer
, uno::UNO_QUERY
);
448 const uno::Any
& a(xPropLayerSet
->getPropertyValue("Name") );
449 bool const bRet
= (a
>>= layerName
);
452 if( layerName
== "DrawnInSlideshow" )
454 //Transform shapes into PolyPolygons
455 importPolygons(xPropSet
);
462 // don't export presentation placeholders on masterpage
463 // they can be non empty when user edits the default texts
464 if(mbConvertingMasterPage
)
466 if( shapeType
== "com.sun.star.presentation.TitleTextShape" || shapeType
== "com.sun.star.presentation.OutlinerShape" )
475 void ShapeImporter::importPolygons(uno::Reference
<beans::XPropertySet
> const& xPropSet
) {
477 drawing::PointSequenceSequence aRetval
;
478 sal_Int32 nLineColor
=0;
480 getPropertyValue( aRetval
, xPropSet
, "PolyPolygon" );
481 getPropertyValue( nLineColor
, xPropSet
, "LineColor" );
482 getPropertyValue( fLineWidth
, xPropSet
, "LineWidth" );
484 drawing::PointSequence
* pOuterSequence
= aRetval
.getArray();
485 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
487 ::basegfx::B2DPolygon aPoly
;
488 basegfx::B2DPoint aPoint
;
489 for( sal_Int32 nCurrPoly
=0; nCurrPoly
<pOuterSequence
->getLength(); ++nCurrPoly
, ++pInnerSequence
)
491 aPoint
.setX((*pInnerSequence
).X
);
492 aPoint
.setY((*pInnerSequence
).Y
);
493 aPoly
.append( aPoint
);
495 UnoViewVector::const_iterator aIter
=(mrContext
.mrViewContainer
).begin();
496 UnoViewVector::const_iterator aEnd
=(mrContext
.mrViewContainer
).end();
499 ::cppcanvas::PolyPolygonSharedPtr
pPolyPoly(
500 ::cppcanvas::BaseGfxFactory::createPolyPolygon( (*aIter
)->getCanvas(),
504 pPolyPoly
->setRGBALineColor( unoColor2RGBColor( nLineColor
).getIntegerColor() );
505 pPolyPoly
->setStrokeWidth(fLineWidth
);
507 maPolygons
.push_back(pPolyPoly
);
513 ShapeSharedPtr
ShapeImporter::importBackgroundShape() // throw (ShapeLoadFailedException)
515 if( maShapesStack
.empty() )
516 throw ShapeLoadFailedException();
518 XShapesEntry
& rTop
= maShapesStack
.top();
519 ShapeSharedPtr
pBgShape(
520 createBackgroundShape(mxPage
,
521 uno::Reference
<drawing::XDrawPage
>(
523 uno::UNO_QUERY_THROW
),
525 mnAscendingPrio
+= 1.0;
530 ShapeSharedPtr
ShapeImporter::importShape() // throw (ShapeLoadFailedException)
533 bool bIsGroupShape
= false;
535 while( !maShapesStack
.empty() && !pRet
)
537 XShapesEntry
& rTop
= maShapesStack
.top();
538 if( rTop
.mnPos
< rTop
.mnCount
)
540 uno::Reference
<drawing::XShape
> const xCurrShape(
541 rTop
.mxShapes
->getByIndex( rTop
.mnPos
), uno::UNO_QUERY
);
543 uno::Reference
<beans::XPropertySet
> xPropSet(
544 xCurrShape
, uno::UNO_QUERY
);
547 // we definitely need the properties of
548 // the shape here. This will also fail,
549 // if getByIndex did not return a valid
551 throw ShapeLoadFailedException();
554 //Retrieve the layer for the current shape
555 uno::Reference
< drawing::XLayer
> xDrawnInSlideshow
;
557 uno::Reference
< drawing::XLayerSupplier
> xLayerSupplier(mxPagesSupplier
, uno::UNO_QUERY
);
558 if(xLayerSupplier
.is())
560 uno::Reference
< container::XNameAccess
> xNameAccess
= xLayerSupplier
->getLayerManager();
562 uno::Reference
< drawing::XLayerManager
> xLayerManager(xNameAccess
, uno::UNO_QUERY
);
564 xDrawnInSlideshow
= xLayerManager
->getLayerForShape(xCurrShape
);
567 OUString
const shapeType( xCurrShape
->getShapeType());
569 // is this shape presentation-invisible?
570 if( !isSkip(xPropSet
, shapeType
, xDrawnInSlideshow
) )
572 bIsGroupShape
= shapeType
== "com.sun.star.drawing.GroupShape";
574 if( rTop
.mpGroupShape
) // in group particle mode?
576 pRet
.reset( new ShapeOfGroup(
577 rTop
.mpGroupShape
/* container shape */,
578 xCurrShape
, xPropSet
,
583 pRet
= createShape( xCurrShape
, xPropSet
, shapeType
);
585 mnAscendingPrio
+= 1.0;
588 if( rTop
.mnPos
>= rTop
.mnCount
)
590 // group or top-level shapes finished:
593 if( bIsGroupShape
&& pRet
)
595 // push new group on the stack: group traversal
596 maShapesStack
.push( XShapesEntry( pRet
) );
603 bool ShapeImporter::isImportDone() const
605 return maShapesStack
.empty();
608 PolyPolygonVector
ShapeImporter::getPolygons()
613 ShapeImporter::ShapeImporter( uno::Reference
<drawing::XDrawPage
> const& xPage
,
614 uno::Reference
<drawing::XDrawPage
> const& xActualPage
,
615 uno::Reference
<drawing::XDrawPagesSupplier
> const& xPagesSupplier
,
616 const SlideShowContext
& rContext
,
617 sal_Int32 nOrdNumStart
,
618 bool bConvertingMasterPage
) :
619 mxPage( xActualPage
),
620 mxPagesSupplier( xPagesSupplier
),
621 mrContext( rContext
),
624 mnAscendingPrio( nOrdNumStart
),
625 mbConvertingMasterPage( bConvertingMasterPage
)
627 uno::Reference
<drawing::XShapes
> const xShapes(
628 xPage
, uno::UNO_QUERY_THROW
);
629 maShapesStack
.push( XShapesEntry(xShapes
) );
632 } // namespace internal
633 } // namespace presentation
635 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */