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 "cachedprimitivebase.hxx"
35 #include "polypolyaction.hxx"
36 #include "outdevstate.hxx"
37 #include "mtftools.hxx"
40 using namespace ::com::sun::star
;
48 class PolyPolyAction
: public CachedPrimitiveBase
51 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
52 const CanvasSharedPtr
&,
56 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
57 const CanvasSharedPtr
&,
63 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
64 const Subset
& rSubset
) const override
;
66 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
67 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
68 const Subset
& rSubset
) const override
;
70 virtual sal_Int32
getActionCount() const override
;
74 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
75 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
77 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
78 const ::basegfx::B2DRange maBounds
;
79 const CanvasSharedPtr mpCanvas
;
81 // stroke color is now implicit: the maState.DeviceColor member
82 rendering::RenderState maState
;
84 uno::Sequence
< double > maFillColor
;
87 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
88 const CanvasSharedPtr
& rCanvas
,
89 const OutDevState
& rState
,
92 CachedPrimitiveBase( rCanvas
, false ),
93 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
94 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
99 tools::initRenderState(maState
,rState
);
102 maFillColor
= rState
.fillColor
;
105 maState
.DeviceColor
= rState
.lineColor
;
108 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
109 const CanvasSharedPtr
& rCanvas
,
110 const OutDevState
& rState
,
113 int nTransparency
) :
114 CachedPrimitiveBase( rCanvas
, false ),
115 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
116 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
121 tools::initRenderState(maState
,rState
);
125 maFillColor
= rState
.fillColor
;
127 if( maFillColor
.getLength() < 4 )
128 maFillColor
.realloc( 4 );
130 // TODO(F1): Color management
131 // adapt fill color transparency
132 maFillColor
[3] = 1.0 - nTransparency
/ 100.0;
137 maState
.DeviceColor
= rState
.lineColor
;
139 if( maState
.DeviceColor
.getLength() < 4 )
140 maState
.DeviceColor
.realloc( 4 );
142 // TODO(F1): Color management
143 // adapt fill color transparency
144 maState
.DeviceColor
[3] = 1.0 - nTransparency
/ 100.0;
148 bool PolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
149 const ::basegfx::B2DHomMatrix
& rTransformation
) const
151 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
152 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
154 rendering::RenderState
aLocalState( maState
);
155 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
157 if( maFillColor
.getLength() )
159 // TODO(E3): Use DBO's finalizer here,
160 // fillPolyPolygon() might throw
161 const uno::Sequence
< double > aTmpColor( aLocalState
.DeviceColor
);
162 aLocalState
.DeviceColor
= maFillColor
;
164 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillPolyPolygon( mxPolyPoly
,
165 mpCanvas
->getViewState(),
168 aLocalState
.DeviceColor
= aTmpColor
;
171 if( aLocalState
.DeviceColor
.getLength() )
173 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->drawPolyPolygon( mxPolyPoly
,
174 mpCanvas
->getViewState(),
181 bool PolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
182 const Subset
& rSubset
) const
184 // TODO(F1): Split up poly-polygon into polygons, or even
185 // line segments, when subsets are requested.
187 // polygon only contains a single action, fail if subset
188 // requests different range
189 if( rSubset
.mnSubsetBegin
!= 0 ||
190 rSubset
.mnSubsetEnd
!= 1 )
193 return CachedPrimitiveBase::render( rTransformation
);
196 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
198 rendering::RenderState
aLocalState( maState
);
199 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
201 return tools::calcDevicePixelBounds(
203 mpCanvas
->getViewState(),
207 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
208 const Subset
& rSubset
) const
210 // TODO(F1): Split up poly-polygon into polygons, or even
211 // line segments, when subsets are requested.
213 // polygon only contains a single action, empty bounds
214 // if subset requests different range
215 if( rSubset
.mnSubsetBegin
!= 0 ||
216 rSubset
.mnSubsetEnd
!= 1 )
217 return ::basegfx::B2DRange();
219 return getBounds( rTransformation
);
222 sal_Int32
PolyPolyAction::getActionCount() const
224 // TODO(F1): Split up poly-polygon into polygons, or even
225 // line segments, when subsets are requested.
230 class TexturedPolyPolyAction
: public CachedPrimitiveBase
233 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
234 const CanvasSharedPtr
& rCanvas
,
235 const OutDevState
& rState
,
236 const rendering::Texture
& rTexture
);
238 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
239 const Subset
& rSubset
) const override
;
241 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
242 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
243 const Subset
& rSubset
) const override
;
245 virtual sal_Int32
getActionCount() const override
;
248 using Action::render
;
249 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
250 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
252 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
253 const ::basegfx::B2DRectangle maBounds
;
254 const CanvasSharedPtr mpCanvas
;
256 // stroke color is now implicit: the maState.DeviceColor member
257 rendering::RenderState maState
;
258 const rendering::Texture maTexture
;
261 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
262 const CanvasSharedPtr
& rCanvas
,
263 const OutDevState
& rState
,
264 const rendering::Texture
& rTexture
) :
265 CachedPrimitiveBase( rCanvas
, true ),
266 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
267 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
270 maTexture( rTexture
)
272 tools::initRenderState(maState
,rState
);
275 bool TexturedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
276 const ::basegfx::B2DHomMatrix
& rTransformation
) const
278 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
279 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
281 rendering::RenderState
aLocalState( maState
);
282 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
284 uno::Sequence
< rendering::Texture
> aSeq(1);
287 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly
,
288 mpCanvas
->getViewState(),
294 bool TexturedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
295 const Subset
& rSubset
) const
297 // TODO(F1): Split up poly-polygon into polygons, or even
298 // line segments, when subsets are requested.
300 // polygon only contains a single action, fail if subset
301 // requests different range
302 if( rSubset
.mnSubsetBegin
!= 0 ||
303 rSubset
.mnSubsetEnd
!= 1 )
306 return CachedPrimitiveBase::render( rTransformation
);
309 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
311 rendering::RenderState
aLocalState( maState
);
312 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
314 return tools::calcDevicePixelBounds(
316 mpCanvas
->getViewState(),
320 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
321 const Subset
& rSubset
) const
323 // TODO(F1): Split up poly-polygon into polygons, or even
324 // line segments, when subsets are requested.
326 // polygon only contains a single action, empty bounds
327 // if subset requests different range
328 if( rSubset
.mnSubsetBegin
!= 0 ||
329 rSubset
.mnSubsetEnd
!= 1 )
330 return ::basegfx::B2DRange();
332 return getBounds( rTransformation
);
335 sal_Int32
TexturedPolyPolyAction::getActionCount() const
337 // TODO(F1): Split up poly-polygon into polygons, or even
338 // line segments, when subsets are requested.
343 class StrokedPolyPolyAction
: public CachedPrimitiveBase
346 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
347 const CanvasSharedPtr
& rCanvas
,
348 const OutDevState
& rState
,
349 const rendering::StrokeAttributes
& rStrokeAttributes
);
351 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
352 const Subset
& rSubset
) const override
;
354 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
355 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
356 const Subset
& rSubset
) const override
;
358 virtual sal_Int32
getActionCount() const override
;
361 using Action::render
;
362 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
363 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
365 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
366 const ::basegfx::B2DRectangle maBounds
;
367 const CanvasSharedPtr mpCanvas
;
368 rendering::RenderState maState
;
369 const rendering::StrokeAttributes maStrokeAttributes
;
372 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
373 const CanvasSharedPtr
& rCanvas
,
374 const OutDevState
& rState
,
375 const rendering::StrokeAttributes
& rStrokeAttributes
) :
376 CachedPrimitiveBase( rCanvas
, false ),
377 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
378 maBounds( ::basegfx::tools::getRange(rPolyPoly
) ),
381 maStrokeAttributes( rStrokeAttributes
)
383 tools::initRenderState(maState
,rState
);
384 maState
.DeviceColor
= rState
.lineColor
;
387 bool StrokedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
388 const ::basegfx::B2DHomMatrix
& rTransformation
) const
390 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
391 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
393 rendering::RenderState
aLocalState( maState
);
394 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
396 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->strokePolyPolygon( mxPolyPoly
,
397 mpCanvas
->getViewState(),
399 maStrokeAttributes
);
403 bool StrokedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
404 const Subset
& rSubset
) const
406 // TODO(F1): Split up poly-polygon into polygons, or even
407 // line segments, when subsets are requested.
409 // polygon only contains a single action, fail if subset
410 // requests different range
411 if( rSubset
.mnSubsetBegin
!= 0 ||
412 rSubset
.mnSubsetEnd
!= 1 )
415 return CachedPrimitiveBase::render( rTransformation
);
418 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
420 rendering::RenderState
aLocalState( maState
);
421 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
423 return tools::calcDevicePixelBounds(
425 mpCanvas
->getViewState(),
429 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
430 const Subset
& rSubset
) const
432 // TODO(F1): Split up poly-polygon into polygons, or even
433 // line segments, when subsets are requested.
435 // polygon only contains a single action, empty bounds
436 // if subset requests different range
437 if( rSubset
.mnSubsetBegin
!= 0 ||
438 rSubset
.mnSubsetEnd
!= 1 )
439 return ::basegfx::B2DRange();
441 return getBounds( rTransformation
);
444 sal_Int32
StrokedPolyPolyAction::getActionCount() const
446 // TODO(F1): Split up poly-polygon into polygons, or even
447 // line segments, when subsets are requested.
452 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
453 const CanvasSharedPtr
& rCanvas
,
454 const OutDevState
& rState
)
456 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
457 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
458 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
459 rState
.isFillColorSet
,
460 rState
.isLineColorSet
) );
463 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
464 const CanvasSharedPtr
& rCanvas
,
465 const OutDevState
& rState
,
466 const rendering::Texture
& rTexture
)
468 return ActionSharedPtr( new TexturedPolyPolyAction( rPoly
, rCanvas
, rState
, rTexture
) );
471 ActionSharedPtr
PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
472 const CanvasSharedPtr
& rCanvas
,
473 const OutDevState
& rState
)
475 OSL_ENSURE( rState
.isLineColorSet
,
476 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
478 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
480 rState
.isLineColorSet
) );
483 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
484 const CanvasSharedPtr
& rCanvas
,
485 const OutDevState
& rState
,
486 const rendering::StrokeAttributes
& rStrokeAttributes
)
488 OSL_ENSURE( rState
.isLineColorSet
,
489 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
490 return ActionSharedPtr( new StrokedPolyPolyAction( rPoly
, rCanvas
, rState
, rStrokeAttributes
) );
493 ActionSharedPtr
PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
494 const CanvasSharedPtr
& rCanvas
,
495 const OutDevState
& rState
,
498 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
499 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
500 return ActionSharedPtr( new PolyPolyAction( rPoly
, rCanvas
, rState
,
501 rState
.isFillColorSet
,
502 rState
.isLineColorSet
,
509 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */