1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <rtl/logfile.hxx>
32 #include <com/sun/star/rendering/XCanvas.hpp>
33 #include <com/sun/star/rendering/TexturingMode.hpp>
35 #include <tools/gen.hxx>
36 #include <vcl/canvastools.hxx>
38 #include <basegfx/range/b2drectangle.hxx>
39 #include <basegfx/tools/canvastools.hxx>
40 #include <basegfx/polygon/b2dpolypolygon.hxx>
41 #include <basegfx/polygon/b2dpolypolygontools.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <canvas/canvastools.hxx>
45 #include <boost/utility.hpp>
47 #include "cachedprimitivebase.hxx"
48 #include "polypolyaction.hxx"
49 #include "outdevstate.hxx"
50 #include "mtftools.hxx"
53 using namespace ::com::sun::star
;
61 class PolyPolyAction
: public CachedPrimitiveBase
64 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
65 const CanvasSharedPtr
&,
69 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
70 const CanvasSharedPtr
&,
76 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
77 const Subset
& rSubset
) const;
79 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
80 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
81 const Subset
& rSubset
) const;
83 virtual sal_Int32
getActionCount() const;
87 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
88 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
90 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
91 const ::basegfx::B2DRange maBounds
;
92 const CanvasSharedPtr mpCanvas
;
94 // stroke color is now implicit: the maState.DeviceColor member
95 rendering::RenderState maState
;
97 uno::Sequence
< double > maFillColor
;
100 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
101 const CanvasSharedPtr
& rCanvas
,
102 const OutDevState
& rState
,
105 CachedPrimitiveBase( rCanvas
, false ),
106 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
107 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
112 tools::initRenderState(maState
,rState
);
115 maFillColor
= rState
.fillColor
;
118 maState
.DeviceColor
= rState
.lineColor
;
121 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
122 const CanvasSharedPtr
& rCanvas
,
123 const OutDevState
& rState
,
126 int nTransparency
) :
127 CachedPrimitiveBase( rCanvas
, false ),
128 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
129 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
134 tools::initRenderState(maState
,rState
);
138 maFillColor
= rState
.fillColor
;
140 if( maFillColor
.getLength() < 4 )
141 maFillColor
.realloc( 4 );
143 // TODO(F1): Color management
144 // adapt fill color transparency
145 maFillColor
[3] = 1.0 - nTransparency
/ 100.0;
150 maState
.DeviceColor
= rState
.lineColor
;
152 if( maState
.DeviceColor
.getLength() < 4 )
153 maState
.DeviceColor
.realloc( 4 );
155 // TODO(F1): Color management
156 // adapt fill color transparency
157 maState
.DeviceColor
[3] = 1.0 - nTransparency
/ 100.0;
161 bool PolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
162 const ::basegfx::B2DHomMatrix
& rTransformation
) const
164 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
165 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
167 rendering::RenderState
aLocalState( maState
);
168 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
170 if( maFillColor
.getLength() )
172 // TODO(E3): Use DBO's finalizer here,
173 // fillPolyPolygon() might throw
174 const uno::Sequence
< double > aTmpColor( aLocalState
.DeviceColor
);
175 aLocalState
.DeviceColor
= maFillColor
;
177 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillPolyPolygon( mxPolyPoly
,
178 mpCanvas
->getViewState(),
181 aLocalState
.DeviceColor
= aTmpColor
;
184 if( aLocalState
.DeviceColor
.getLength() )
186 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->drawPolyPolygon( mxPolyPoly
,
187 mpCanvas
->getViewState(),
194 bool PolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
195 const Subset
& rSubset
) const
197 // TODO(F1): Split up poly-polygon into polygons, or even
198 // line segments, when subsets are requested.
200 // polygon only contains a single action, fail if subset
201 // requests different range
202 if( rSubset
.mnSubsetBegin
!= 0 ||
203 rSubset
.mnSubsetEnd
!= 1 )
206 return CachedPrimitiveBase::render( rTransformation
);
209 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
211 rendering::RenderState
aLocalState( maState
);
212 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
214 return tools::calcDevicePixelBounds(
216 mpCanvas
->getViewState(),
220 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
221 const Subset
& rSubset
) const
223 // TODO(F1): Split up poly-polygon into polygons, or even
224 // line segments, when subsets are requested.
226 // polygon only contains a single action, empty bounds
227 // if subset requests different range
228 if( rSubset
.mnSubsetBegin
!= 0 ||
229 rSubset
.mnSubsetEnd
!= 1 )
230 return ::basegfx::B2DRange();
232 return getBounds( rTransformation
);
235 sal_Int32
PolyPolyAction::getActionCount() const
237 // TODO(F1): Split up poly-polygon into polygons, or even
238 // line segments, when subsets are requested.
243 // -------------------------------------------------------------------------------
245 class TexturedPolyPolyAction
: public CachedPrimitiveBase
248 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
249 const CanvasSharedPtr
& rCanvas
,
250 const OutDevState
& rState
,
251 const rendering::Texture
& rTexture
);
253 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
254 const Subset
& rSubset
) const;
256 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
257 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
258 const Subset
& rSubset
) const;
260 virtual sal_Int32
getActionCount() const;
263 using Action::render
;
264 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
265 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
267 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
268 const ::basegfx::B2DRectangle maBounds
;
269 const CanvasSharedPtr mpCanvas
;
271 // stroke color is now implicit: the maState.DeviceColor member
272 rendering::RenderState maState
;
273 const rendering::Texture maTexture
;
276 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
277 const CanvasSharedPtr
& rCanvas
,
278 const OutDevState
& rState
,
279 const rendering::Texture
& rTexture
) :
280 CachedPrimitiveBase( rCanvas
, true ),
281 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
282 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
285 maTexture( rTexture
)
287 tools::initRenderState(maState
,rState
);
290 bool TexturedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
291 const ::basegfx::B2DHomMatrix
& rTransformation
) const
293 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
294 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
296 rendering::RenderState
aLocalState( maState
);
297 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
299 uno::Sequence
< rendering::Texture
> aSeq(1);
302 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly
,
303 mpCanvas
->getViewState(),
309 bool TexturedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
310 const Subset
& rSubset
) const
312 // TODO(F1): Split up poly-polygon into polygons, or even
313 // line segments, when subsets are requested.
315 // polygon only contains a single action, fail if subset
316 // requests different range
317 if( rSubset
.mnSubsetBegin
!= 0 ||
318 rSubset
.mnSubsetEnd
!= 1 )
321 return CachedPrimitiveBase::render( rTransformation
);
324 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
326 rendering::RenderState
aLocalState( maState
);
327 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
329 return tools::calcDevicePixelBounds(
331 mpCanvas
->getViewState(),
335 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
336 const Subset
& rSubset
) const
338 // TODO(F1): Split up poly-polygon into polygons, or even
339 // line segments, when subsets are requested.
341 // polygon only contains a single action, empty bounds
342 // if subset requests different range
343 if( rSubset
.mnSubsetBegin
!= 0 ||
344 rSubset
.mnSubsetEnd
!= 1 )
345 return ::basegfx::B2DRange();
347 return getBounds( rTransformation
);
350 sal_Int32
TexturedPolyPolyAction::getActionCount() const
352 // TODO(F1): Split up poly-polygon into polygons, or even
353 // line segments, when subsets are requested.
357 // -------------------------------------------------------------------------------
359 class StrokedPolyPolyAction
: public CachedPrimitiveBase
362 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
363 const CanvasSharedPtr
& rCanvas
,
364 const OutDevState
& rState
,
365 const rendering::StrokeAttributes
& rStrokeAttributes
);
367 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
368 const Subset
& rSubset
) const;
370 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
371 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
372 const Subset
& rSubset
) const;
374 virtual sal_Int32
getActionCount() const;
377 using Action::render
;
378 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
379 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
381 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
382 const ::basegfx::B2DRectangle maBounds
;
383 const CanvasSharedPtr mpCanvas
;
384 rendering::RenderState maState
;
385 const rendering::StrokeAttributes maStrokeAttributes
;
388 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
389 const CanvasSharedPtr
& rCanvas
,
390 const OutDevState
& rState
,
391 const rendering::StrokeAttributes
& rStrokeAttributes
) :
392 CachedPrimitiveBase( rCanvas
, false ),
393 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
394 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
397 maStrokeAttributes( rStrokeAttributes
)
399 tools::initRenderState(maState
,rState
);
400 maState
.DeviceColor
= rState
.lineColor
;
403 bool StrokedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
404 const ::basegfx::B2DHomMatrix
& rTransformation
) const
406 RTL_LOGFILE_CONTEXT( aLog
, "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
407 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::cppcanvas::internal::PolyPolyAction: 0x%X", this );
409 rendering::RenderState
aLocalState( maState
);
410 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
412 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->strokePolyPolygon( mxPolyPoly
,
413 mpCanvas
->getViewState(),
415 maStrokeAttributes
);
419 bool StrokedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
420 const Subset
& rSubset
) const
422 // TODO(F1): Split up poly-polygon into polygons, or even
423 // line segments, when subsets are requested.
425 // polygon only contains a single action, fail if subset
426 // requests different range
427 if( rSubset
.mnSubsetBegin
!= 0 ||
428 rSubset
.mnSubsetEnd
!= 1 )
431 return CachedPrimitiveBase::render( rTransformation
);
434 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
436 rendering::RenderState
aLocalState( maState
);
437 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
439 return tools::calcDevicePixelBounds(
441 mpCanvas
->getViewState(),
445 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
446 const Subset
& rSubset
) const
448 // TODO(F1): Split up poly-polygon into polygons, or even
449 // line segments, when subsets are requested.
451 // polygon only contains a single action, empty bounds
452 // if subset requests different range
453 if( rSubset
.mnSubsetBegin
!= 0 ||
454 rSubset
.mnSubsetEnd
!= 1 )
455 return ::basegfx::B2DRange();
457 return getBounds( rTransformation
);
460 sal_Int32
StrokedPolyPolyAction::getActionCount() const
462 // TODO(F1): Split up poly-polygon into polygons, or even
463 // line segments, when subsets are requested.
468 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
469 const CanvasSharedPtr
& rCanvas
,
470 const OutDevState
& rState
)
472 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
473 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
474 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
475 rState
.isFillColorSet
,
476 rState
.isLineColorSet
) );
479 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
480 const CanvasSharedPtr
& rCanvas
,
481 const OutDevState
& rState
,
482 const rendering::Texture
& rTexture
)
484 return ActionSharedPtr( new TexturedPolyPolyAction( rPoly
, rCanvas
, rState
, rTexture
) );
487 ActionSharedPtr
PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
488 const CanvasSharedPtr
& rCanvas
,
489 const OutDevState
& rState
)
491 OSL_ENSURE( rState
.isLineColorSet
,
492 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
494 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
496 rState
.isLineColorSet
) );
499 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
500 const CanvasSharedPtr
& rCanvas
,
501 const OutDevState
& rState
,
502 const rendering::StrokeAttributes
& rStrokeAttributes
)
504 OSL_ENSURE( rState
.isLineColorSet
,
505 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
506 return ActionSharedPtr( new StrokedPolyPolyAction( rPoly
, rCanvas
, rState
, rStrokeAttributes
) );
509 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
510 const CanvasSharedPtr
& rCanvas
,
511 const OutDevState
& rState
,
514 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
515 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
516 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
517 rState
.isFillColorSet
,
518 rState
.isLineColorSet
,
525 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */