Bump version to 21.06.18.1
[LibreOffice.git] / cppcanvas / source / mtfrenderer / polypolyaction.cxx
blob6d679cbd0a81e7c70bc4905a25bd87dd0e97ce3c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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
43 namespace
45 class PolyPolyAction : public CachedPrimitiveBase
47 public:
48 PolyPolyAction( const ::basegfx::B2DPolyPolygon&,
49 const CanvasSharedPtr&,
50 const OutDevState&,
51 bool bFill,
52 bool bStroke );
53 PolyPolyAction( const ::basegfx::B2DPolyPolygon&,
54 const CanvasSharedPtr&,
55 const OutDevState&,
56 bool bFill,
57 bool bStroke,
58 int nTransparency );
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;
69 private:
70 using Action::render;
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,
87 bool bFill,
88 bool bStroke ) :
89 CachedPrimitiveBase( rCanvas, false ),
90 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ),
91 maBounds( ::basegfx::utils::getRange(rPolyPoly) ),
92 mpCanvas( rCanvas ),
93 maState(),
94 maFillColor()
96 tools::initRenderState(maState,rState);
98 if( bFill )
99 maFillColor = rState.fillColor;
101 if( bStroke )
102 maState.DeviceColor = rState.lineColor;
105 PolyPolyAction::PolyPolyAction( const ::basegfx::B2DPolyPolygon& rPolyPoly,
106 const CanvasSharedPtr& rCanvas,
107 const OutDevState& rState,
108 bool bFill,
109 bool bStroke,
110 int nTransparency ) :
111 CachedPrimitiveBase( rCanvas, false ),
112 mxPolyPoly( ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( rCanvas->getUNOCanvas()->getDevice(), rPolyPoly) ),
113 maBounds( ::basegfx::utils::getRange(rPolyPoly) ),
114 mpCanvas( rCanvas ),
115 maState(),
116 maFillColor()
118 tools::initRenderState(maState,rState);
120 if( bFill )
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;
132 if( bStroke )
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(),
163 aLocalState );
165 aLocalState.DeviceColor = aTmpColor;
168 if( aLocalState.DeviceColor.hasElements() )
170 rCachedPrimitive = mpCanvas->getUNOCanvas()->drawPolyPolygon( mxPolyPoly,
171 mpCanvas->getViewState(),
172 aLocalState );
175 return true;
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 )
188 return false;
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(
199 maBounds,
200 mpCanvas->getViewState(),
201 aLocalState );
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.
223 return 1;
227 class TexturedPolyPolyAction : public CachedPrimitiveBase
229 public:
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;
244 private:
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) ),
265 mpCanvas( rCanvas ),
266 maState(),
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);
282 aSeq[0] = maTexture;
284 rCachedPrimitive = mpCanvas->getUNOCanvas()->fillTexturedPolyPolygon( mxPolyPoly,
285 mpCanvas->getViewState(),
286 aLocalState,
287 aSeq );
288 return true;
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 )
301 return false;
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(
312 maBounds,
313 mpCanvas->getViewState(),
314 aLocalState );
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.
336 return 1;
340 class StrokedPolyPolyAction : public CachedPrimitiveBase
342 public:
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;
357 private:
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) ),
376 mpCanvas( rCanvas ),
377 maState(),
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(),
395 aLocalState,
396 maStrokeAttributes );
397 return true;
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 )
410 return false;
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(
421 maBounds,
422 mpCanvas->getViewState(),
423 aLocalState );
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.
445 return 1;
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,
476 false,
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,
493 int nTransparency )
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,
500 nTransparency );
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */