fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / slideshow / source / engine / shapes / shapeimporter.cxx
blobb0826834ed84b91d6a31bb03416bc308755d87f4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 // must be first
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"
53 #include "tools.hxx"
54 #include "slideshowcontext.hxx"
56 #include <boost/shared_ptr.hpp>
57 #include <boost/scoped_ptr.hpp>
59 using namespace com::sun::star;
61 namespace slideshow {
62 namespace internal {
64 namespace {
66 bool importShapeGraphic(
67 GraphicObject & o_rGraphic,
68 uno::Reference<beans::XPropertySet> const& xPropSet )
70 OUString aURL;
71 if( !getPropertyValue( aURL, xPropSet, "GraphicURL") ||
72 aURL.isEmpty() )
74 // no or empty property - cannot import shape graphic
75 return false;
78 OUString const aVndUrl(
79 "vnd.sun.star.GraphicObject:" );
80 sal_Int32 nIndex( aURL.indexOf( aVndUrl ) );
82 if(nIndex != -1)
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" );
91 return false;
94 // unique ID string found in URL, extract
95 // to separate string
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
113 return false;
116 else
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" );
129 return false;
132 Graphic aTmpGraphic;
133 if( GraphicConverter::Import(
134 *pGraphicStream, aTmpGraphic ) != ERRCODE_NONE )
136 OSL_FAIL( "ShapeImporter::importShape(): "
137 "Failed to import shape graphic from given URL" );
138 return false;
141 o_rGraphic = GraphicObject( aTmpGraphic );
143 return true;
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
151 public:
152 ShapeOfGroup( ShapeSharedPtr const& pGroupShape,
153 uno::Reference<drawing::XShape> const& xShape,
154 uno::Reference<beans::XPropertySet> const& xPropSet,
155 double nPrio );
157 // Shape:
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;
173 private:
174 ShapeSharedPtr const mpGroupShape;
175 uno::Reference<drawing::XShape> const mxShape;
176 double const mnPrio;
177 basegfx::B2DPoint maPosOffset;
178 double mnWidth;
179 double mnHeight;
182 ShapeOfGroup::ShapeOfGroup( ShapeSharedPtr const& pGroupShape,
183 uno::Reference<drawing::XShape> const& xShape,
184 uno::Reference<beans::XPropertySet> const& xPropSet,
185 double nPrio ) :
186 mpGroupShape(pGroupShape),
187 mxShape(xShape),
188 mnPrio(nPrio)
190 // read bound rect
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
202 return mxShape;
205 void ShapeOfGroup::addViewLayer( ViewLayerSharedPtr const& /*pNewLayer*/,
206 bool /*bRedrawLayer*/ )
210 bool ShapeOfGroup::removeViewLayer( ViewLayerSharedPtr const& /*pNewLayer*/ )
212 return true;
215 bool ShapeOfGroup::clearAllViewLayers()
217 return true;
220 bool ShapeOfGroup::update() const
222 return true;
225 bool ShapeOfGroup::render() const
227 return true;
230 bool ShapeOfGroup::isContentChanged() const
232 return false;
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
245 return getBounds();
248 basegfx::B2DRectangle ShapeOfGroup::getUpdateArea() const
250 return getBounds();
253 bool ShapeOfGroup::isVisible() const
255 return mpGroupShape->isVisible();
258 double ShapeOfGroup::getPriority() const
260 return mnPrio;
263 bool ShapeOfGroup::isBackgroundDetached() const
265 return false;
268 } // anon namespace
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,
279 mnAscendingPrio,
280 mrContext);
282 else if( shapeType == "com.sun.star.drawing.PluginShape" )
284 // PropertyValues to copy from XShape to plugin
285 static const char* aPropertyValues[] =
287 "PluginURL",
288 "PluginMimeType",
289 "PluginCommands"
292 // (Netscape)Plugin shape. This is a special object
293 return createAppletShape( xCurrShape,
294 mnAscendingPrio,
295 OUString( "com.sun.star.comp.sfx2.PluginObject" ),
296 aPropertyValues,
297 SAL_N_ELEMENTS(aPropertyValues),
298 mrContext );
300 else if( shapeType == "com.sun.star.drawing.AppletShape" )
302 // PropertyValues to copy from XShape to applet
303 static const char* aPropertyValues[] =
305 "AppletCodeBase",
306 "AppletName",
307 "AppletCode",
308 "AppletCommands",
309 "AppletIsScript"
312 // (Java)Applet shape. This is a special object
313 return createAppletShape( xCurrShape,
314 mnAscendingPrio,
315 OUString( "com.sun.star.comp.sfx2.AppletObject" ),
316 aPropertyValues,
317 SAL_N_ELEMENTS(aPropertyValues),
318 mrContext );
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,
325 mxPage,
326 mnAscendingPrio,
327 true,
328 mrContext );
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
337 // animation frame)
338 if( !importShapeGraphic( aGraphicObject, xPropSet ) )
339 return ShapeSharedPtr(); // error loading graphic -
340 // no placeholders in
341 // slideshow
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,
351 mxPage,
352 mnAscendingPrio,
353 true,
354 mrContext );
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);
364 sal_Int16 nRed(0);
365 sal_Int16 nGreen(0);
366 sal_Int16 nBlue(0);
367 double nGamma(1.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,
396 aGraphCrop.Top,
397 aGraphCrop.Right,
398 aGraphCrop.Bottom );
401 // fetch readily transformed and color-modified
402 // graphic
405 Graphic aGraphic(
406 aGraphicObject.GetTransformedGraphic(
407 aGraphicObject.GetPrefSize(),
408 aGraphicObject.GetPrefMapMode(),
409 aGraphAttrs ) );
411 return DrawShape::create( xCurrShape,
412 mxPage,
413 mnAscendingPrio,
414 aGraphic,
415 mrContext );
417 else
419 return DrawShape::create( xCurrShape,
420 mxPage,
421 mnAscendingPrio,
422 false,
423 mrContext );
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:
433 bool bEmpty = false;
434 if( getPropertyValue( bEmpty,
435 xPropSet,
436 "IsEmptyPresentationObject") &&
437 bEmpty )
439 return true;
442 //skip shapes which corresponds to annotations
443 if(xLayer.is())
445 OUString layerName;
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);
450 if(bRet)
452 if( layerName == "DrawnInSlideshow" )
454 //Transform shapes into PolyPolygons
455 importPolygons(xPropSet);
457 return true;
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" )
468 return true;
471 return false;
475 void ShapeImporter::importPolygons(uno::Reference<beans::XPropertySet> const& xPropSet) {
477 drawing::PointSequenceSequence aRetval;
478 sal_Int32 nLineColor=0;
479 double fLineWidth;
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();
497 while(aIter != aEnd)
499 ::cppcanvas::PolyPolygonSharedPtr pPolyPoly(
500 ::cppcanvas::BaseGfxFactory::createPolyPolygon( (*aIter)->getCanvas(),
501 aPoly ) );
502 if( pPolyPoly )
504 pPolyPoly->setRGBALineColor( unoColor2RGBColor( nLineColor ).getIntegerColor() );
505 pPolyPoly->setStrokeWidth(fLineWidth);
506 pPolyPoly->draw();
507 maPolygons.push_back(pPolyPoly);
509 ++aIter;
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>(
522 rTop.mxShapes,
523 uno::UNO_QUERY_THROW),
524 mrContext) );
525 mnAscendingPrio += 1.0;
527 return pBgShape;
530 ShapeSharedPtr ShapeImporter::importShape() // throw (ShapeLoadFailedException)
532 ShapeSharedPtr pRet;
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 );
542 ++rTop.mnPos;
543 uno::Reference<beans::XPropertySet> xPropSet(
544 xCurrShape, uno::UNO_QUERY );
545 if( !xPropSet.is() )
547 // we definitely need the properties of
548 // the shape here. This will also fail,
549 // if getByIndex did not return a valid
550 // shape
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,
579 mnAscendingPrio ) );
581 else
583 pRet = createShape( xCurrShape, xPropSet, shapeType );
585 mnAscendingPrio += 1.0;
588 if( rTop.mnPos >= rTop.mnCount )
590 // group or top-level shapes finished:
591 maShapesStack.pop();
593 if( bIsGroupShape && pRet )
595 // push new group on the stack: group traversal
596 maShapesStack.push( XShapesEntry( pRet ) );
600 return pRet;
603 bool ShapeImporter::isImportDone() const
605 return maShapesStack.empty();
608 PolyPolygonVector ShapeImporter::getPolygons()
610 return maPolygons;
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 ),
622 maPolygons(),
623 maShapesStack(),
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: */