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
) ),
94 tools::initRenderState(maState
,rState
);
97 maFillColor
= rState
.fillColor
;
100 maState
.DeviceColor
= rState
.lineColor
;
103 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
104 const CanvasSharedPtr
& rCanvas
,
105 const OutDevState
& rState
,
108 int nTransparency
) :
109 CachedPrimitiveBase( rCanvas
, false ),
110 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
111 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
114 tools::initRenderState(maState
,rState
);
118 maFillColor
= rState
.fillColor
;
120 if( maFillColor
.getLength() < 4 )
121 maFillColor
.realloc( 4 );
123 // TODO(F1): Color management
124 // adapt fill color transparency
125 maFillColor
.getArray()[3] = 1.0 - nTransparency
/ 100.0;
130 maState
.DeviceColor
= rState
.lineColor
;
132 if( maState
.DeviceColor
.getLength() < 4 )
133 maState
.DeviceColor
.realloc( 4 );
135 // TODO(F1): Color management
136 // adapt fill color transparency
137 maState
.DeviceColor
.getArray()[3] = 1.0 - nTransparency
/ 100.0;
141 bool PolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
142 const ::basegfx::B2DHomMatrix
& rTransformation
) const
144 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
145 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
147 rendering::RenderState
aLocalState( maState
);
148 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
150 if( maFillColor
.hasElements() )
152 // TODO(E3): Use DBO's finalizer here,
153 // fillPolyPolygon() might throw
154 const uno::Sequence
< double > aTmpColor( aLocalState
.DeviceColor
);
155 aLocalState
.DeviceColor
= maFillColor
;
157 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillPolyPolygon( mxPolyPoly
,
158 mpCanvas
->getViewState(),
161 aLocalState
.DeviceColor
= aTmpColor
;
164 if( aLocalState
.DeviceColor
.hasElements() )
166 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->drawPolyPolygon( mxPolyPoly
,
167 mpCanvas
->getViewState(),
174 bool PolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
175 const Subset
& rSubset
) const
177 // TODO(F1): Split up poly-polygon into polygons, or even
178 // line segments, when subsets are requested.
180 // polygon only contains a single action, fail if subset
181 // requests different range
182 if( rSubset
.mnSubsetBegin
!= 0 ||
183 rSubset
.mnSubsetEnd
!= 1 )
186 return CachedPrimitiveBase::render( rTransformation
);
189 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
191 rendering::RenderState
aLocalState( maState
);
192 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
194 return tools::calcDevicePixelBounds(
196 mpCanvas
->getViewState(),
200 ::basegfx::B2DRange
PolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
201 const Subset
& rSubset
) const
203 // TODO(F1): Split up poly-polygon into polygons, or even
204 // line segments, when subsets are requested.
206 // polygon only contains a single action, empty bounds
207 // if subset requests different range
208 if( rSubset
.mnSubsetBegin
!= 0 ||
209 rSubset
.mnSubsetEnd
!= 1 )
210 return ::basegfx::B2DRange();
212 return getBounds( rTransformation
);
215 sal_Int32
PolyPolyAction::getActionCount() const
217 // TODO(F1): Split up poly-polygon into polygons, or even
218 // line segments, when subsets are requested.
223 class TexturedPolyPolyAction
: public CachedPrimitiveBase
226 TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
227 const CanvasSharedPtr
& rCanvas
,
228 const OutDevState
& rState
,
229 const rendering::Texture
& rTexture
);
231 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
232 const Subset
& rSubset
) const override
;
234 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
235 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
236 const Subset
& rSubset
) const override
;
238 virtual sal_Int32
getActionCount() const override
;
241 using Action::render
;
242 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
243 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
245 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
246 const ::basegfx::B2DRectangle maBounds
;
247 const CanvasSharedPtr mpCanvas
;
249 // stroke color is now implicit: the maState.DeviceColor member
250 rendering::RenderState maState
;
251 const rendering::Texture maTexture
;
254 TexturedPolyPolyAction::TexturedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
255 const CanvasSharedPtr
& rCanvas
,
256 const OutDevState
& rState
,
257 const rendering::Texture
& rTexture
) :
258 CachedPrimitiveBase( rCanvas
, true ),
259 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
260 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
262 maTexture( rTexture
)
264 tools::initRenderState(maState
,rState
);
267 bool TexturedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
268 const ::basegfx::B2DHomMatrix
& rTransformation
) const
270 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
271 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
273 rendering::RenderState
aLocalState( maState
);
274 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
276 uno::Sequence
< rendering::Texture
> aSeq
{ maTexture
};
278 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly
,
279 mpCanvas
->getViewState(),
285 bool TexturedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
286 const Subset
& rSubset
) const
288 // TODO(F1): Split up poly-polygon into polygons, or even
289 // line segments, when subsets are requested.
291 // polygon only contains a single action, fail if subset
292 // requests different range
293 if( rSubset
.mnSubsetBegin
!= 0 ||
294 rSubset
.mnSubsetEnd
!= 1 )
297 return CachedPrimitiveBase::render( rTransformation
);
300 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
302 rendering::RenderState
aLocalState( maState
);
303 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
305 return tools::calcDevicePixelBounds(
307 mpCanvas
->getViewState(),
311 ::basegfx::B2DRange
TexturedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
312 const Subset
& rSubset
) const
314 // TODO(F1): Split up poly-polygon into polygons, or even
315 // line segments, when subsets are requested.
317 // polygon only contains a single action, empty bounds
318 // if subset requests different range
319 if( rSubset
.mnSubsetBegin
!= 0 ||
320 rSubset
.mnSubsetEnd
!= 1 )
321 return ::basegfx::B2DRange();
323 return getBounds( rTransformation
);
326 sal_Int32
TexturedPolyPolyAction::getActionCount() const
328 // TODO(F1): Split up poly-polygon into polygons, or even
329 // line segments, when subsets are requested.
334 class StrokedPolyPolyAction
: public CachedPrimitiveBase
337 StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
338 const CanvasSharedPtr
& rCanvas
,
339 const OutDevState
& rState
,
340 const rendering::StrokeAttributes
& rStrokeAttributes
);
342 virtual bool renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
343 const Subset
& rSubset
) const override
;
345 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
346 virtual ::basegfx::B2DRange
getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
,
347 const Subset
& rSubset
) const override
;
349 virtual sal_Int32
getActionCount() const override
;
352 using Action::render
;
353 virtual bool renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
354 const ::basegfx::B2DHomMatrix
& rTransformation
) const override
;
356 const uno::Reference
< rendering::XPolyPolygon2D
> mxPolyPoly
;
357 const ::basegfx::B2DRectangle maBounds
;
358 const CanvasSharedPtr mpCanvas
;
359 rendering::RenderState maState
;
360 const rendering::StrokeAttributes maStrokeAttributes
;
363 StrokedPolyPolyAction::StrokedPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPolyPoly
,
364 const CanvasSharedPtr
& rCanvas
,
365 const OutDevState
& rState
,
366 const rendering::StrokeAttributes
& rStrokeAttributes
) :
367 CachedPrimitiveBase( rCanvas
, false ),
368 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas
->getUNOCanvas()->getDevice(), rPolyPoly
) ),
369 maBounds( ::basegfx::utils::getRange(rPolyPoly
) ),
371 maStrokeAttributes( rStrokeAttributes
)
373 tools::initRenderState(maState
,rState
);
374 maState
.DeviceColor
= rState
.lineColor
;
377 bool StrokedPolyPolyAction::renderPrimitive( uno::Reference
< rendering::XCachedPrimitive
>& rCachedPrimitive
,
378 const ::basegfx::B2DHomMatrix
& rTransformation
) const
380 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction::renderPrimitive()" );
381 SAL_INFO( "cppcanvas.emf", "::cppcanvas::internal::PolyPolyAction: 0x" << std::hex
<< this );
383 rendering::RenderState
aLocalState( maState
);
384 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
386 rCachedPrimitive
= mpCanvas
->getUNOCanvas()->strokePolyPolygon( mxPolyPoly
,
387 mpCanvas
->getViewState(),
389 maStrokeAttributes
);
393 bool StrokedPolyPolyAction::renderSubset( const ::basegfx::B2DHomMatrix
& rTransformation
,
394 const Subset
& rSubset
) const
396 // TODO(F1): Split up poly-polygon into polygons, or even
397 // line segments, when subsets are requested.
399 // polygon only contains a single action, fail if subset
400 // requests different range
401 if( rSubset
.mnSubsetBegin
!= 0 ||
402 rSubset
.mnSubsetEnd
!= 1 )
405 return CachedPrimitiveBase::render( rTransformation
);
408 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( const ::basegfx::B2DHomMatrix
& rTransformation
) const
410 rendering::RenderState
aLocalState( maState
);
411 ::canvas::tools::prependToRenderState(aLocalState
, rTransformation
);
413 return tools::calcDevicePixelBounds(
415 mpCanvas
->getViewState(),
419 ::basegfx::B2DRange
StrokedPolyPolyAction::getBounds( 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, empty bounds
426 // if subset requests different range
427 if( rSubset
.mnSubsetBegin
!= 0 ||
428 rSubset
.mnSubsetEnd
!= 1 )
429 return ::basegfx::B2DRange();
431 return getBounds( rTransformation
);
434 sal_Int32
StrokedPolyPolyAction::getActionCount() const
436 // TODO(F1): Split up poly-polygon into polygons, or even
437 // line segments, when subsets are requested.
442 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
443 const CanvasSharedPtr
& rCanvas
,
444 const OutDevState
& rState
)
446 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
447 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
448 return std::make_shared
<PolyPolyAction
>( rPoly
, rCanvas
, rState
,
449 rState
.isFillColorSet
,
450 rState
.isLineColorSet
);
453 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
454 const CanvasSharedPtr
& rCanvas
,
455 const OutDevState
& rState
,
456 const rendering::Texture
& rTexture
)
458 return std::make_shared
<TexturedPolyPolyAction
>( rPoly
, rCanvas
, rState
, rTexture
);
461 std::shared_ptr
<Action
> PolyPolyActionFactory::createLinePolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
462 const CanvasSharedPtr
& rCanvas
,
463 const OutDevState
& rState
)
465 OSL_ENSURE( rState
.isLineColorSet
,
466 "PolyPolyActionFactory::createLinePolyPolyAction() called with empty line color" );
468 return std::make_shared
<PolyPolyAction
>( rPoly
, rCanvas
, rState
,
470 rState
.isLineColorSet
);
473 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
474 const CanvasSharedPtr
& rCanvas
,
475 const OutDevState
& rState
,
476 const rendering::StrokeAttributes
& rStrokeAttributes
)
478 OSL_ENSURE( rState
.isLineColorSet
,
479 "PolyPolyActionFactory::createPolyPolyAction() for strokes called with empty line color" );
480 return std::make_shared
<StrokedPolyPolyAction
>( rPoly
, rCanvas
, rState
, rStrokeAttributes
);
483 std::shared_ptr
<Action
> PolyPolyActionFactory::createPolyPolyAction( const ::basegfx::B2DPolyPolygon
& rPoly
,
484 const CanvasSharedPtr
& rCanvas
,
485 const OutDevState
& rState
,
488 OSL_ENSURE( rState
.isLineColorSet
|| rState
.isFillColorSet
,
489 "PolyPolyActionFactory::createPolyPolyAction() with empty line and fill color" );
490 return std::make_shared
<PolyPolyAction
>( rPoly
, rCanvas
, rState
,
491 rState
.isFillColorSet
,
492 rState
.isLineColorSet
,
498 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */