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 <com/sun/star/rendering/XCanvas.hpp>
22 #include <com/sun/star/rendering/TexturingMode.hpp>
24 #include <sal/types.h>
25 #include <vcl/canvastools.hxx>
27 #include <basegfx/range/b2drectangle.hxx>
28 #include <basegfx/tools/canvastools.hxx>
29 #include <basegfx/polygon/b2dpolypolygon.hxx>
30 #include <basegfx/polygon/b2dpolypolygontools.hxx>
31 #include <basegfx/matrix/b2dhommatrix.hxx>
32 #include <canvas/canvastools.hxx>
34 #include <boost/utility.hpp>
36 #include "cachedprimitivebase.hxx"
37 #include "polypolyaction.hxx"
38 #include "outdevstate.hxx"
39 #include "mtftools.hxx"
42 using namespace ::com::sun::star
;
50 class PolyPolyAction
: public CachedPrimitiveBase
53 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
54 const CanvasSharedPtr
&,
58 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
59 const CanvasSharedPtr
&,
65 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
66 const Subset
& rSubset
) const;
68 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
69 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
70 const Subset
& rSubset
) const;
72 virtual sal_Int32
getActionCount() const;
76 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
77 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
79 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
80 const ::basegfx::B2DRange maBounds
;
81 const CanvasSharedPtr mpCanvas
;
83 // stroke color is now implicit: the maState.DeviceColor member
84 rendering::RenderState maState
;
86 uno::Sequence
< double > maFillColor
;
89 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
90 const CanvasSharedPtr
& rCanvas
,
91 const OutDevState
& rState
,
94 CachedPrimitiveBase( rCanvas
, false ),
95 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
96 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
101 tools::initRenderState(maState
,rState
);
104 maFillColor
= rState
.fillColor
;
107 maState
.DeviceColor
= rState
.lineColor
;
110 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
111 const CanvasSharedPtr
& rCanvas
,
112 const OutDevState
& rState
,
115 int nTransparency
) :
116 CachedPrimitiveBase( rCanvas
, false ),
117 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
118 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
123 tools::initRenderState(maState
,rState
);
127 maFillColor
= rState
.fillColor
;
129 if( maFillColor
.getLength() < 4 )
130 maFillColor
.realloc( 4 );
132 // TODO(F1): Color management
133 // adapt fill color transparency
134 maFillColor
[3] = 1.0 - nTransparency
/ 100.0;
139 maState
.DeviceColor
= rState
.lineColor
;
141 if( maState
.DeviceColor
.getLength() < 4 )
142 maState
.DeviceColor
.realloc( 4 );
144 // TODO(F1): Color management
145 // adapt fill color transparency
146 maState
.DeviceColor
[3] = 1.0 - nTransparency
/ 100.0;
150 bool PolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
151 const ::basegfx::B2DHomMatrix
& rTransformation
) const
153 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
154 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
156 rendering::RenderState
aLocalState( maState
);
157 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
159 if( maFillColor
.getLength() )
161 // TODO(E3): Use DBO's finalizer here,
162 // fillPolyPolygon() might throw
163 const uno::Sequence
< double > aTmpColor( aLocalState
.DeviceColor
);
164 aLocalState
.DeviceColor
= maFillColor
;
166 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillPolyPolygon( mxPolyPoly
,
167 mpCanvas
->getViewState(),
170 aLocalState
.DeviceColor
= aTmpColor
;
173 if( aLocalState
.DeviceColor
.getLength() )
175 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->drawPolyPolygon( mxPolyPoly
,
176 mpCanvas
->getViewState(),
183 bool PolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
184 const Subset
& rSubset
) const
186 // TODO(F1): Split up poly-polygon into polygons, or even
187 // line segments, when subsets are requested.
189 // polygon only contains a single action, fail if subset
190 // requests different range
191 if( rSubset
.mnSubsetBegin
!= 0 ||
192 rSubset
.mnSubsetEnd
!= 1 )
195 return CachedPrimitiveBase::render( rTransformation
);
198 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
200 rendering::RenderState
aLocalState( maState
);
201 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
203 return tools::calcDevicePixelBounds(
205 mpCanvas
->getViewState(),
209 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
210 const Subset
& rSubset
) const
212 // TODO(F1): Split up poly-polygon into polygons, or even
213 // line segments, when subsets are requested.
215 // polygon only contains a single action, empty bounds
216 // if subset requests different range
217 if( rSubset
.mnSubsetBegin
!= 0 ||
218 rSubset
.mnSubsetEnd
!= 1 )
219 return ::basegfx::B2DRange();
221 return getBounds( rTransformation
);
224 sal_Int32
PolyPolyAction::getActionCount() const
226 // TODO(F1): Split up poly-polygon into polygons, or even
227 // line segments, when subsets are requested.
232 // -------------------------------------------------------------------------------
234 class TexturedPolyPolyAction
: public CachedPrimitiveBase
237 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
238 const CanvasSharedPtr
& rCanvas
,
239 const OutDevState
& rState
,
240 const rendering::Texture
& rTexture
);
242 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
243 const Subset
& rSubset
) const;
245 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
246 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
247 const Subset
& rSubset
) const;
249 virtual sal_Int32
getActionCount() const;
252 using Action::render
;
253 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
254 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
256 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
257 const ::basegfx::B2DRectangle maBounds
;
258 const CanvasSharedPtr mpCanvas
;
260 // stroke color is now implicit: the maState.DeviceColor member
261 rendering::RenderState maState
;
262 const rendering::Texture maTexture
;
265 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
266 const CanvasSharedPtr
& rCanvas
,
267 const OutDevState
& rState
,
268 const rendering::Texture
& rTexture
) :
269 CachedPrimitiveBase( rCanvas
, true ),
270 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
271 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
274 maTexture( rTexture
)
276 tools::initRenderState(maState
,rState
);
279 bool TexturedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
280 const ::basegfx::B2DHomMatrix
& rTransformation
) const
282 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
283 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
285 rendering::RenderState
aLocalState( maState
);
286 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
288 uno::Sequence
< rendering::Texture
> aSeq(1);
291 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly
,
292 mpCanvas
->getViewState(),
298 bool TexturedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
299 const Subset
& rSubset
) const
301 // TODO(F1): Split up poly-polygon into polygons, or even
302 // line segments, when subsets are requested.
304 // polygon only contains a single action, fail if subset
305 // requests different range
306 if( rSubset
.mnSubsetBegin
!= 0 ||
307 rSubset
.mnSubsetEnd
!= 1 )
310 return CachedPrimitiveBase::render( rTransformation
);
313 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
315 rendering::RenderState
aLocalState( maState
);
316 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
318 return tools::calcDevicePixelBounds(
320 mpCanvas
->getViewState(),
324 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
325 const Subset
& rSubset
) const
327 // TODO(F1): Split up poly-polygon into polygons, or even
328 // line segments, when subsets are requested.
330 // polygon only contains a single action, empty bounds
331 // if subset requests different range
332 if( rSubset
.mnSubsetBegin
!= 0 ||
333 rSubset
.mnSubsetEnd
!= 1 )
334 return ::basegfx::B2DRange();
336 return getBounds( rTransformation
);
339 sal_Int32
TexturedPolyPolyAction::getActionCount() const
341 // TODO(F1): Split up poly-polygon into polygons, or even
342 // line segments, when subsets are requested.
346 // -------------------------------------------------------------------------------
348 class StrokedPolyPolyAction
: public CachedPrimitiveBase
351 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
352 const CanvasSharedPtr
& rCanvas
,
353 const OutDevState
& rState
,
354 const rendering::StrokeAttributes
& rStrokeAttributes
);
356 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
357 const Subset
& rSubset
) const;
359 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const;
360 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
361 const Subset
& rSubset
) const;
363 virtual sal_Int32
getActionCount() const;
366 using Action::render
;
367 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
368 const ::basegfx::B2DHomMatrix
& rTransformation
) const;
370 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
371 const ::basegfx::B2DRectangle maBounds
;
372 const CanvasSharedPtr mpCanvas
;
373 rendering::RenderState maState
;
374 const rendering::StrokeAttributes maStrokeAttributes
;
377 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
378 const CanvasSharedPtr
& rCanvas
,
379 const OutDevState
& rState
,
380 const rendering::StrokeAttributes
& rStrokeAttributes
) :
381 CachedPrimitiveBase( rCanvas
, false ),
382 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
383 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
386 maStrokeAttributes( rStrokeAttributes
)
388 tools::initRenderState(maState
,rState
);
389 maState
.DeviceColor
= rState
.lineColor
;
392 bool StrokedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
393 const ::basegfx::B2DHomMatrix
& rTransformation
) const
395 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
396 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
398 rendering::RenderState
aLocalState( maState
);
399 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
401 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->strokePolyPolygon( mxPolyPoly
,
402 mpCanvas
->getViewState(),
404 maStrokeAttributes
);
408 bool StrokedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
409 const Subset
& rSubset
) const
411 // TODO(F1): Split up poly-polygon into polygons, or even
412 // line segments, when subsets are requested.
414 // polygon only contains a single action, fail if subset
415 // requests different range
416 if( rSubset
.mnSubsetBegin
!= 0 ||
417 rSubset
.mnSubsetEnd
!= 1 )
420 return CachedPrimitiveBase::render( rTransformation
);
423 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
425 rendering::RenderState
aLocalState( maState
);
426 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
428 return tools::calcDevicePixelBounds(
430 mpCanvas
->getViewState(),
434 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
435 const Subset
& rSubset
) const
437 // TODO(F1): Split up poly-polygon into polygons, or even
438 // line segments, when subsets are requested.
440 // polygon only contains a single action, empty bounds
441 // if subset requests different range
442 if( rSubset
.mnSubsetBegin
!= 0 ||
443 rSubset
.mnSubsetEnd
!= 1 )
444 return ::basegfx::B2DRange();
446 return getBounds( rTransformation
);
449 sal_Int32
StrokedPolyPolyAction::getActionCount() const
451 // TODO(F1): Split up poly-polygon into polygons, or even
452 // line segments, when subsets are requested.
457 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
458 const CanvasSharedPtr
& rCanvas
,
459 const OutDevState
& rState
)
461 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
462 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
463 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
464 rState
.isFillColorSet
,
465 rState
.isLineColorSet
) );
468 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
469 const CanvasSharedPtr
& rCanvas
,
470 const OutDevState
& rState
,
471 const rendering::Texture
& rTexture
)
473 return ActionSharedPtr( new TexturedPolyPolyAction( rPoly
, rCanvas
, rState
, rTexture
) );
476 ActionSharedPtr
PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
477 const CanvasSharedPtr
& rCanvas
,
478 const OutDevState
& rState
)
480 OSL_ENSURE( rState
.isLineColorSet
,
481 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
483 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
485 rState
.isLineColorSet
) );
488 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
489 const CanvasSharedPtr
& rCanvas
,
490 const OutDevState
& rState
,
491 const rendering::StrokeAttributes
& rStrokeAttributes
)
493 OSL_ENSURE( rState
.isLineColorSet
,
494 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
495 return ActionSharedPtr( new StrokedPolyPolyAction( rPoly
, rCanvas
, rState
, rStrokeAttributes
) );
498 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
499 const CanvasSharedPtr
& rCanvas
,
500 const OutDevState
& rState
,
503 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
504 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
505 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
506 rState
.isFillColorSet
,
507 rState
.isLineColorSet
,
514 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */