1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: polypolyaction.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppcanvas.hxx"
34 #include <rtl/logfile.hxx>
36 #include <com/sun/star/rendering/XCanvas.hpp>
37 #include <com/sun/star/rendering/TexturingMode.hpp>
39 #include <tools/gen.hxx>
40 #include <vcl/canvastools.hxx>
42 #include <basegfx/range/b2drectangle.hxx>
43 #include <basegfx/tools/canvastools.hxx>
44 #include <basegfx/polygon/b2dpolypolygon.hxx>
45 #include <basegfx/polygon/b2dpolypolygontools.hxx>
46 #include <basegfx/matrix/b2dhommatrix.hxx>
47 #include <canvas/canvastools.hxx>
49 #include <boost/utility.hpp>
51 #include "cachedprimitivebase.hxx"
52 #include "polypolyaction.hxx"
53 #include "outdevstate.hxx"
54 #include "mtftools.hxx"
57 using namespace ::com::sun::star
;
65 class PolyPolyAction
: public CachedPrimitiveBase
68 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
69 const CanvasSharedPtr
&,
73 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
74 const CanvasSharedPtr
&,
80 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
81 const Subset
& rSubset
) const;
83 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
84 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
85 const Subset
& rSubset
) const;
87 virtual sal_Int32
getActionCount() const;
91 virtual bool render( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
92 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
94 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
95 const ::basegfx::B2DRange maBounds
;
96 const CanvasSharedPtr mpCanvas
;
98 // stroke color is now implicit: the maState.DeviceColor member
99 rendering::RenderState maState
;
101 uno::Sequence
< double > maFillColor
;
104 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
105 const CanvasSharedPtr
& rCanvas
,
106 const OutDevState
& rState
,
109 CachedPrimitiveBase( rCanvas
, false ),
110 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
111 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
116 tools::initRenderState(maState
,rState
);
119 maFillColor
= rState
.fillColor
;
122 maState
.DeviceColor
= rState
.lineColor
;
125 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
126 const CanvasSharedPtr
& rCanvas
,
127 const OutDevState
& rState
,
130 int nTransparency
) :
131 CachedPrimitiveBase( rCanvas
, false ),
132 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
133 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
138 tools::initRenderState(maState
,rState
);
142 maFillColor
= rState
.fillColor
;
144 if( maFillColor
.getLength() < 4 )
145 maFillColor
.realloc( 4 );
147 // TODO(F1): Color management
148 // adapt fill color transparency
149 maFillColor
[3] = 1.0 - nTransparency
/ 100.0;
154 maState
.DeviceColor
= rState
.lineColor
;
156 if( maState
.DeviceColor
.getLength() < 4 )
157 maState
.DeviceColor
.realloc( 4 );
159 // TODO(F1): Color management
160 // adapt fill color transparency
161 maState
.DeviceColor
[3] = 1.0 - nTransparency
/ 100.0;
165 bool PolyPolyAction::render( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
166 const ::basegfx::B2DHomMatrix
& rTransformation
) const
168 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::PolyPolyAction::render()" );
169 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
171 rendering::RenderState
aLocalState( maState
);
172 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
175 aLocalState
.Clip
.clear();
176 aLocalState
.DeviceColor
=
177 ::vcl::unotools::colorToDoubleSequence( mpCanvas
->getUNOCanvas()->getDevice(),
178 ::Color( 0x80FF0000 ) );
180 if( maState
.Clip
.is() )
181 mpCanvas
->getUNOCanvas()->fillPolyPolygon( maState
.Clip
,
182 mpCanvas
->getViewState(),
185 aLocalState
.DeviceColor
= maState
.DeviceColor
;
188 if( maFillColor
.getLength() )
190 // TODO(E3): Use DBO's finalizer here,
191 // fillPolyPolygon() might throw
192 const uno::Sequence
< double > aTmpColor( aLocalState
.DeviceColor
);
193 aLocalState
.DeviceColor
= maFillColor
;
195 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillPolyPolygon( mxPolyPoly
,
196 mpCanvas
->getViewState(),
199 aLocalState
.DeviceColor
= aTmpColor
;
202 if( aLocalState
.DeviceColor
.getLength() )
204 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->drawPolyPolygon( mxPolyPoly
,
205 mpCanvas
->getViewState(),
212 bool PolyPolyAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
213 const Subset
& rSubset
) const
215 // TODO(F1): Split up poly-polygon into polygons, or even
216 // line segments, when subsets are requested.
218 // polygon only contains a single action, fail if subset
219 // requests different range
220 if( rSubset
.mnSubsetBegin
!= 0 ||
221 rSubset
.mnSubsetEnd
!= 1 )
224 return CachedPrimitiveBase::render( rTransformation
);
227 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
229 rendering::RenderState
aLocalState( maState
);
230 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
232 return tools::calcDevicePixelBounds(
234 mpCanvas
->getViewState(),
238 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
239 const Subset
& rSubset
) const
241 // TODO(F1): Split up poly-polygon into polygons, or even
242 // line segments, when subsets are requested.
244 // polygon only contains a single action, empty bounds
245 // if subset requests different range
246 if( rSubset
.mnSubsetBegin
!= 0 ||
247 rSubset
.mnSubsetEnd
!= 1 )
248 return ::basegfx::B2DRange();
250 return getBounds( rTransformation
);
253 sal_Int32
PolyPolyAction::getActionCount() const
255 // TODO(F1): Split up poly-polygon into polygons, or even
256 // line segments, when subsets are requested.
261 // -------------------------------------------------------------------------------
263 class TexturedPolyPolyAction
: public CachedPrimitiveBase
266 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
267 const CanvasSharedPtr
& rCanvas
,
268 const OutDevState
& rState
,
269 const rendering::Texture
& rTexture
);
271 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
272 const Subset
& rSubset
) const;
274 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
275 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
276 const Subset
& rSubset
) const;
278 virtual sal_Int32
getActionCount() const;
281 using Action::render
;
282 virtual bool render( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
283 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
285 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
286 const ::basegfx::B2DRectangle maBounds
;
287 const CanvasSharedPtr mpCanvas
;
289 // stroke color is now implicit: the maState.DeviceColor member
290 rendering::RenderState maState
;
291 const rendering::Texture maTexture
;
294 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
295 const CanvasSharedPtr
& rCanvas
,
296 const OutDevState
& rState
,
297 const rendering::Texture
& rTexture
) :
298 CachedPrimitiveBase( rCanvas
, true ),
299 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
300 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
303 maTexture( rTexture
)
305 tools::initRenderState(maState
,rState
);
308 bool TexturedPolyPolyAction::render( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
309 const ::basegfx::B2DHomMatrix
& rTransformation
) const
311 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::PolyPolyAction::render()" );
312 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
314 rendering::RenderState
aLocalState( maState
);
315 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
317 uno::Sequence
< rendering::Texture
> aSeq(1);
320 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly
,
321 mpCanvas
->getViewState(),
327 bool TexturedPolyPolyAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
328 const Subset
& rSubset
) const
330 // TODO(F1): Split up poly-polygon into polygons, or even
331 // line segments, when subsets are requested.
333 // polygon only contains a single action, fail if subset
334 // requests different range
335 if( rSubset
.mnSubsetBegin
!= 0 ||
336 rSubset
.mnSubsetEnd
!= 1 )
339 return CachedPrimitiveBase::render( rTransformation
);
342 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
344 rendering::RenderState
aLocalState( maState
);
345 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
347 return tools::calcDevicePixelBounds(
349 mpCanvas
->getViewState(),
353 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
354 const Subset
& rSubset
) const
356 // TODO(F1): Split up poly-polygon into polygons, or even
357 // line segments, when subsets are requested.
359 // polygon only contains a single action, empty bounds
360 // if subset requests different range
361 if( rSubset
.mnSubsetBegin
!= 0 ||
362 rSubset
.mnSubsetEnd
!= 1 )
363 return ::basegfx::B2DRange();
365 return getBounds( rTransformation
);
368 sal_Int32
TexturedPolyPolyAction::getActionCount() const
370 // TODO(F1): Split up poly-polygon into polygons, or even
371 // line segments, when subsets are requested.
375 // -------------------------------------------------------------------------------
377 class StrokedPolyPolyAction
: public CachedPrimitiveBase
380 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
381 const CanvasSharedPtr
& rCanvas
,
382 const OutDevState
& rState
,
383 const rendering::StrokeAttributes
& rStrokeAttributes
);
385 virtual bool render( const ::basegfx::B2DHomMatrix
& rTransformation
,
386 const Subset
& rSubset
) const;
388 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
389 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
390 const Subset
& rSubset
) const;
392 virtual sal_Int32
getActionCount() const;
395 using Action::render
;
396 virtual bool render( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
397 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
399 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
400 const ::basegfx::B2DRectangle maBounds
;
401 const CanvasSharedPtr mpCanvas
;
402 rendering::RenderState maState
;
403 const rendering::StrokeAttributes maStrokeAttributes
;
406 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
407 const CanvasSharedPtr
& rCanvas
,
408 const OutDevState
& rState
,
409 const rendering::StrokeAttributes
& rStrokeAttributes
) :
410 CachedPrimitiveBase( rCanvas
, false ),
411 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
412 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
415 maStrokeAttributes( rStrokeAttributes
)
417 tools::initRenderState(maState
,rState
);
418 maState
.DeviceColor
= rState
.lineColor
;
421 bool StrokedPolyPolyAction::render( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
422 const ::basegfx::B2DHomMatrix
& rTransformation
) const
424 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::PolyPolyAction::render()" );
425 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
427 rendering::RenderState
aLocalState( maState
);
428 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
430 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->strokePolyPolygon( mxPolyPoly
,
431 mpCanvas
->getViewState(),
433 maStrokeAttributes
);
437 bool StrokedPolyPolyAction::render( const ::basegfx::B2DHomMatrix
& rTransformation
,
438 const Subset
& rSubset
) const
440 // TODO(F1): Split up poly-polygon into polygons, or even
441 // line segments, when subsets are requested.
443 // polygon only contains a single action, fail if subset
444 // requests different range
445 if( rSubset
.mnSubsetBegin
!= 0 ||
446 rSubset
.mnSubsetEnd
!= 1 )
449 return CachedPrimitiveBase::render( rTransformation
);
452 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
454 rendering::RenderState
aLocalState( maState
);
455 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
457 return tools::calcDevicePixelBounds(
459 mpCanvas
->getViewState(),
463 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
464 const Subset
& rSubset
) const
466 // TODO(F1): Split up poly-polygon into polygons, or even
467 // line segments, when subsets are requested.
469 // polygon only contains a single action, empty bounds
470 // if subset requests different range
471 if( rSubset
.mnSubsetBegin
!= 0 ||
472 rSubset
.mnSubsetEnd
!= 1 )
473 return ::basegfx::B2DRange();
475 return getBounds( rTransformation
);
478 sal_Int32
StrokedPolyPolyAction::getActionCount() const
480 // TODO(F1): Split up poly-polygon into polygons, or even
481 // line segments, when subsets are requested.
486 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
487 const CanvasSharedPtr
& rCanvas
,
488 const OutDevState
& rState
)
490 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
491 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
492 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
493 rState
.isFillColorSet
,
494 rState
.isLineColorSet
) );
497 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
498 const CanvasSharedPtr
& rCanvas
,
499 const OutDevState
& rState
,
500 const rendering::Texture
& rTexture
)
502 return ActionSharedPtr( new TexturedPolyPolyAction( rPoly
, rCanvas
, rState
, rTexture
) );
505 ActionSharedPtr
PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
506 const CanvasSharedPtr
& rCanvas
,
507 const OutDevState
& rState
)
509 OSL_ENSURE( rState
.isLineColorSet
,
510 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
512 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
514 rState
.isLineColorSet
) );
517 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
518 const CanvasSharedPtr
& rCanvas
,
519 const OutDevState
& rState
,
520 const rendering::StrokeAttributes
& rStrokeAttributes
)
522 OSL_ENSURE( rState
.isLineColorSet
,
523 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
524 return ActionSharedPtr( new StrokedPolyPolyAction( rPoly
, rCanvas
, rState
, rStrokeAttributes
) );
527 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
528 const CanvasSharedPtr
& rCanvas
,
529 const OutDevState
& rState
,
532 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
533 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
534 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
535 rState
.isFillColorSet
,
536 rState
.isLineColorSet
,