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>
23 #include <sal/types.h>
25 #include <basegfx/range/b2drectangle.hxx>
26 #include <basegfx/utils/canvastools.hxx>
27 #include <basegfx/polygon/b2dpolypolygon.hxx>
28 #include <basegfx/polygon/b2dpolypolygontools.hxx>
29 #include <basegfx/matrix/b2dhommatrix.hxx>
30 #include <canvas/canvastools.hxx>
31 #include <sal/log.hxx>
33 #include "cachedprimitivebase.hxx"
34 #include "polypolyaction.hxx"
35 #include <outdevstate.hxx>
36 #include "mtftools.hxx"
39 using namespace ::com::sun::star
;
41 namespace cppcanvas::internal
45 class PolyPolyAction
: public CachedPrimitiveBase
48 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
49 const CanvasSharedPtr
&,
53 PolyPolyAction( const ::basegfx::B2DPolyPolygon
&,
54 const CanvasSharedPtr
&,
60 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
61 const Subset
& rSubset
) const override
;
63 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
64 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
65 const Subset
& rSubset
) const override
;
67 virtual sal_Int32
getActionCount() const override
;
71 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
72 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
74 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
75 const ::basegfx::B2DRange maBounds
;
76 const CanvasSharedPtr mpCanvas
;
78 // stroke color is now implicit: the maState.DeviceColor member
79 rendering::RenderState maState
;
81 uno::Sequence
< double > maFillColor
;
84 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
85 const CanvasSharedPtr
& rCanvas
,
86 const OutDevState
& rState
,
89 CachedPrimitiveBase( rCanvas
, false ),
90 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
91 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
96 tools::initRenderState(maState
,rState
);
99 maFillColor
= rState
.fillColor
;
102 maState
.DeviceColor
= rState
.lineColor
;
105 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
106 const CanvasSharedPtr
& rCanvas
,
107 const OutDevState
& rState
,
110 int nTransparency
) :
111 CachedPrimitiveBase( rCanvas
, false ),
112 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
113 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
118 tools::initRenderState(maState
,rState
);
122 maFillColor
= rState
.fillColor
;
124 if( maFillColor
.getLength() < 4 )
125 maFillColor
.realloc( 4 );
127 // TODO(F1): Color management
128 // adapt fill color transparency
129 maFillColor
[3] = 1.0 - nTransparency
/ 100.0;
134 maState
.DeviceColor
= rState
.lineColor
;
136 if( maState
.DeviceColor
.getLength() < 4 )
137 maState
.DeviceColor
.realloc( 4 );
139 // TODO(F1): Color management
140 // adapt fill color transparency
141 maState
.DeviceColor
[3] = 1.0 - nTransparency
/ 100.0;
145 bool PolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
146 const ::basegfx::B2DHomMatrix
& rTransformation
) const
148 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
149 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
151 rendering::RenderState
aLocalState( maState
);
152 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
154 if( maFillColor
.hasElements() )
156 // TODO(E3): Use DBO's finalizer here,
157 // fillPolyPolygon() might throw
158 const uno::Sequence
< double > aTmpColor( aLocalState
.DeviceColor
);
159 aLocalState
.DeviceColor
= maFillColor
;
161 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillPolyPolygon( mxPolyPoly
,
162 mpCanvas
->getViewState(),
165 aLocalState
.DeviceColor
= aTmpColor
;
168 if( aLocalState
.DeviceColor
.hasElements() )
170 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->drawPolyPolygon( mxPolyPoly
,
171 mpCanvas
->getViewState(),
178 bool PolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
179 const Subset
& rSubset
) const
181 // TODO(F1): Split up poly-polygon into polygons, or even
182 // line segments, when subsets are requested.
184 // polygon only contains a single action, fail if subset
185 // requests different range
186 if( rSubset
.mnSubsetBegin
!= 0 ||
187 rSubset
.mnSubsetEnd
!= 1 )
190 return CachedPrimitiveBase::render( rTransformation
);
193 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
195 rendering::RenderState
aLocalState( maState
);
196 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
198 return tools::calcDevicePixelBounds(
200 mpCanvas
->getViewState(),
204 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
205 const Subset
& rSubset
) const
207 // TODO(F1): Split up poly-polygon into polygons, or even
208 // line segments, when subsets are requested.
210 // polygon only contains a single action, empty bounds
211 // if subset requests different range
212 if( rSubset
.mnSubsetBegin
!= 0 ||
213 rSubset
.mnSubsetEnd
!= 1 )
214 return ::basegfx::B2DRange();
216 return getBounds( rTransformation
);
219 sal_Int32
PolyPolyAction::getActionCount() const
221 // TODO(F1): Split up poly-polygon into polygons, or even
222 // line segments, when subsets are requested.
227 class TexturedPolyPolyAction
: public CachedPrimitiveBase
230 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
231 const CanvasSharedPtr
& rCanvas
,
232 const OutDevState
& rState
,
233 const rendering::Texture
& rTexture
);
235 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
236 const Subset
& rSubset
) const override
;
238 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
239 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
240 const Subset
& rSubset
) const override
;
242 virtual sal_Int32
getActionCount() const override
;
245 using Action::render
;
246 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
247 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
249 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
250 const ::basegfx::B2DRectangle maBounds
;
251 const CanvasSharedPtr mpCanvas
;
253 // stroke color is now implicit: the maState.DeviceColor member
254 rendering::RenderState maState
;
255 const rendering::Texture maTexture
;
258 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
259 const CanvasSharedPtr
& rCanvas
,
260 const OutDevState
& rState
,
261 const rendering::Texture
& rTexture
) :
262 CachedPrimitiveBase( rCanvas
, true ),
263 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
264 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
267 maTexture( rTexture
)
269 tools::initRenderState(maState
,rState
);
272 bool TexturedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
273 const ::basegfx::B2DHomMatrix
& rTransformation
) const
275 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
276 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
278 rendering::RenderState
aLocalState( maState
);
279 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
281 uno::Sequence
< rendering::Texture
> aSeq(1);
284 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly
,
285 mpCanvas
->getViewState(),
291 bool TexturedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
292 const Subset
& rSubset
) const
294 // TODO(F1): Split up poly-polygon into polygons, or even
295 // line segments, when subsets are requested.
297 // polygon only contains a single action, fail if subset
298 // requests different range
299 if( rSubset
.mnSubsetBegin
!= 0 ||
300 rSubset
.mnSubsetEnd
!= 1 )
303 return CachedPrimitiveBase::render( rTransformation
);
306 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
308 rendering::RenderState
aLocalState( maState
);
309 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
311 return tools::calcDevicePixelBounds(
313 mpCanvas
->getViewState(),
317 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
318 const Subset
& rSubset
) const
320 // TODO(F1): Split up poly-polygon into polygons, or even
321 // line segments, when subsets are requested.
323 // polygon only contains a single action, empty bounds
324 // if subset requests different range
325 if( rSubset
.mnSubsetBegin
!= 0 ||
326 rSubset
.mnSubsetEnd
!= 1 )
327 return ::basegfx::B2DRange();
329 return getBounds( rTransformation
);
332 sal_Int32
TexturedPolyPolyAction::getActionCount() const
334 // TODO(F1): Split up poly-polygon into polygons, or even
335 // line segments, when subsets are requested.
340 class StrokedPolyPolyAction
: public CachedPrimitiveBase
343 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
344 const CanvasSharedPtr
& rCanvas
,
345 const OutDevState
& rState
,
346 const rendering::StrokeAttributes
& rStrokeAttributes
);
348 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
349 const Subset
& rSubset
) const override
;
351 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
352 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
353 const Subset
& rSubset
) const override
;
355 virtual sal_Int32
getActionCount() const override
;
358 using Action::render
;
359 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
360 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
362 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
363 const ::basegfx::B2DRectangle maBounds
;
364 const CanvasSharedPtr mpCanvas
;
365 rendering::RenderState maState
;
366 const rendering::StrokeAttributes maStrokeAttributes
;
369 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
370 const CanvasSharedPtr
& rCanvas
,
371 const OutDevState
& rState
,
372 const rendering::StrokeAttributes
& rStrokeAttributes
) :
373 CachedPrimitiveBase( rCanvas
, false ),
374 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
375 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
378 maStrokeAttributes( rStrokeAttributes
)
380 tools::initRenderState(maState
,rState
);
381 maState
.DeviceColor
= rState
.lineColor
;
384 bool StrokedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
385 const ::basegfx::B2DHomMatrix
& rTransformation
) const
387 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
388 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
390 rendering::RenderState
aLocalState( maState
);
391 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
393 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->strokePolyPolygon( mxPolyPoly
,
394 mpCanvas
->getViewState(),
396 maStrokeAttributes
);
400 bool StrokedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
401 const Subset
& rSubset
) const
403 // TODO(F1): Split up poly-polygon into polygons, or even
404 // line segments, when subsets are requested.
406 // polygon only contains a single action, fail if subset
407 // requests different range
408 if( rSubset
.mnSubsetBegin
!= 0 ||
409 rSubset
.mnSubsetEnd
!= 1 )
412 return CachedPrimitiveBase::render( rTransformation
);
415 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
417 rendering::RenderState
aLocalState( maState
);
418 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
420 return tools::calcDevicePixelBounds(
422 mpCanvas
->getViewState(),
426 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
427 const Subset
& rSubset
) const
429 // TODO(F1): Split up poly-polygon into polygons, or even
430 // line segments, when subsets are requested.
432 // polygon only contains a single action, empty bounds
433 // if subset requests different range
434 if( rSubset
.mnSubsetBegin
!= 0 ||
435 rSubset
.mnSubsetEnd
!= 1 )
436 return ::basegfx::B2DRange();
438 return getBounds( rTransformation
);
441 sal_Int32
StrokedPolyPolyAction::getActionCount() const
443 // TODO(F1): Split up poly-polygon into polygons, or even
444 // line segments, when subsets are requested.
449 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
450 const CanvasSharedPtr
& rCanvas
,
451 const OutDevState
& rState
)
453 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
454 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
455 return std::make_shared
<PolyPolyAction
>( rPoly
, rCanvas
, rState
,
456 rState
.isFillColorSet
,
457 rState
.isLineColorSet
);
460 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
461 const CanvasSharedPtr
& rCanvas
,
462 const OutDevState
& rState
,
463 const rendering::Texture
& rTexture
)
465 return std::make_shared
<TexturedPolyPolyAction
>( rPoly
, rCanvas
, rState
, rTexture
);
468 std::shared_ptr
<Action
> PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
469 const CanvasSharedPtr
& rCanvas
,
470 const OutDevState
& rState
)
472 OSL_ENSURE( rState
.isLineColorSet
,
473 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
475 return std::make_shared
<PolyPolyAction
>( rPoly
, rCanvas
, rState
,
477 rState
.isLineColorSet
);
480 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
481 const CanvasSharedPtr
& rCanvas
,
482 const OutDevState
& rState
,
483 const rendering::StrokeAttributes
& rStrokeAttributes
)
485 OSL_ENSURE( rState
.isLineColorSet
,
486 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
487 return std::make_shared
<StrokedPolyPolyAction
>( rPoly
, rCanvas
, rState
, rStrokeAttributes
);
490 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
491 const CanvasSharedPtr
& rCanvas
,
492 const OutDevState
& rState
,
495 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
496 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
497 return std::make_shared
<PolyPolyAction
>( rPoly
, rCanvas
, rState
,
498 rState
.isFillColorSet
,
499 rState
.isLineColorSet
,
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */