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 .
20 #include "vclpixelprocessor2d.hxx"
21 #include <vcl/outdev.hxx>
22 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
23 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
24 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
25 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
26 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
27 #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
29 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
30 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
31 #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
33 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
34 #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
35 #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
36 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
37 #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
38 #include <com/sun/star/awt/XWindow2.hpp>
39 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
40 #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
41 #include <helperwrongspellrenderer.hxx>
42 #include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <vcl/hatch.hxx>
45 #include <tools/diagnose_ex.h>
46 #include <com/sun/star/awt/PosSize.hpp>
47 #include <drawinglayer/primitive2d/invertprimitive2d.hxx>
49 #include <drawinglayer/primitive2d/backgroundcolorprimitive2d.hxx>
50 #include <basegfx/matrix/b2dhommatrixtools.hxx>
51 #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
52 #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
53 #include <toolkit/helper/vclunohelper.hxx>
54 #include <vcl/window.hxx>
55 #include <svtools/borderhelper.hxx>
57 #include <com/sun/star/table/BorderLineStyle.hpp>
60 using namespace com::sun::star
;
64 basegfx::B2DPolygon
makeRectPolygon( double fX
, double fY
, double fW
, double fH
)
66 basegfx::B2DPolygon aPoly
;
67 aPoly
.append(basegfx::B2DPoint(fX
, fY
));
68 aPoly
.append(basegfx::B2DPoint(fX
+fW
, fY
));
69 aPoly
.append(basegfx::B2DPoint(fX
+fW
, fY
+fH
));
70 aPoly
.append(basegfx::B2DPoint(fX
, fY
+fH
));
71 aPoly
.setClosed(true);
76 OutputDevice
* pOutDev
, double fX1
, double fY1
, double fX2
, double fY2
,
77 const basegfx::BColor
& rColor
)
79 basegfx::B2DPolygon aTarget
;
80 aTarget
.append(basegfx::B2DPoint(fX1
, fY1
));
81 aTarget
.append(basegfx::B2DPoint(fX2
, fY2
));
83 pOutDev
->SetFillColor();
84 pOutDev
->SetLineColor(Color(rColor
));
85 pOutDev
->DrawPolyLine(aTarget
);
90 namespace drawinglayer
94 struct VclPixelProcessor2D::Impl
96 AntialiasingFlags m_nOrigAntiAliasing
;
98 explicit Impl(OutputDevice
const& rOutDev
)
99 : m_nOrigAntiAliasing(rOutDev
.GetAntialiasing())
103 VclPixelProcessor2D::VclPixelProcessor2D(const geometry::ViewInformation2D
& rViewInformation
, OutputDevice
& rOutDev
)
104 : VclProcessor2D(rViewInformation
, rOutDev
)
105 , m_pImpl(new Impl(rOutDev
))
107 // prepare maCurrentTransformation matrix with viewTransformation to target directly to pixels
108 maCurrentTransformation
= rViewInformation
.getObjectToViewTransformation();
110 // prepare output directly to pixels
111 mpOutputDevice
->Push(PushFlags::MAPMODE
);
112 mpOutputDevice
->SetMapMode();
114 // react on AntiAliasing settings
115 if(getOptionsDrawinglayer().IsAntiAliasing())
117 mpOutputDevice
->SetAntialiasing(
118 m_pImpl
->m_nOrigAntiAliasing
| AntialiasingFlags::EnableB2dDraw
);
122 mpOutputDevice
->SetAntialiasing(
123 m_pImpl
->m_nOrigAntiAliasing
& ~AntialiasingFlags::EnableB2dDraw
);
127 VclPixelProcessor2D::~VclPixelProcessor2D()
130 mpOutputDevice
->Pop();
132 // restore AntiAliasing
133 mpOutputDevice
->SetAntialiasing(m_pImpl
->m_nOrigAntiAliasing
);
136 bool VclPixelProcessor2D::tryDrawPolyPolygonColorPrimitive2DDirect(const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D
& rSource
, double fTransparency
)
138 basegfx::B2DPolyPolygon
aLocalPolyPolygon(rSource
.getB2DPolyPolygon());
140 if(!aLocalPolyPolygon
.count())
146 const basegfx::BColor
aPolygonColor(maBColorModifierStack
.getModifiedColor(rSource
.getBColor()));
148 mpOutputDevice
->SetFillColor(Color(aPolygonColor
));
149 mpOutputDevice
->SetLineColor();
150 aLocalPolyPolygon
.transform(maCurrentTransformation
);
151 mpOutputDevice
->DrawTransparent(
158 bool VclPixelProcessor2D::tryDrawPolygonHairlinePrimitive2DDirect(const drawinglayer::primitive2d::PolygonHairlinePrimitive2D
& rSource
, double fTransparency
)
160 basegfx::B2DPolygon
aLocalPolygon(rSource
.getB2DPolygon());
162 if(!aLocalPolygon
.count())
168 const basegfx::BColor
aLineColor(maBColorModifierStack
.getModifiedColor(rSource
.getBColor()));
170 mpOutputDevice
->SetFillColor();
171 mpOutputDevice
->SetLineColor(Color(aLineColor
));
172 aLocalPolygon
.transform(maCurrentTransformation
);
174 // try drawing; if it did not work, use standard fallback
175 if(mpOutputDevice
->DrawPolyLineDirect( aLocalPolygon
, 0.0, fTransparency
))
183 bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect(const drawinglayer::primitive2d::PolygonStrokePrimitive2D
& rSource
, double fTransparency
)
185 basegfx::B2DPolygon
aLocalPolygon(rSource
.getB2DPolygon());
187 if(!aLocalPolygon
.count())
193 aLocalPolygon
= basegfx::tools::simplifyCurveSegments(aLocalPolygon
);
194 basegfx::B2DPolyPolygon aHairLinePolyPolygon
;
196 if(rSource
.getStrokeAttribute().isDefault() || 0.0 == rSource
.getStrokeAttribute().getFullDotDashLen())
198 // no line dashing, just copy
199 aHairLinePolyPolygon
.append(aLocalPolygon
);
204 basegfx::tools::applyLineDashing(
206 rSource
.getStrokeAttribute().getDotDashArray(),
207 &aHairLinePolyPolygon
,
209 rSource
.getStrokeAttribute().getFullDotDashLen());
212 if(!aHairLinePolyPolygon
.count())
218 const basegfx::BColor
aLineColor(
219 maBColorModifierStack
.getModifiedColor(
220 rSource
.getLineAttribute().getColor()));
222 mpOutputDevice
->SetFillColor();
223 mpOutputDevice
->SetLineColor(Color(aLineColor
));
224 aHairLinePolyPolygon
.transform(maCurrentTransformation
);
226 double fLineWidth(rSource
.getLineAttribute().getWidth());
228 if(basegfx::fTools::more(fLineWidth
, 0.0))
230 basegfx::B2DVector
aLineWidth(fLineWidth
, 0.0);
232 aLineWidth
= maCurrentTransformation
* aLineWidth
;
233 fLineWidth
= aLineWidth
.getLength();
236 // draw simple hairline for small line widths
237 // see also RenderPolygonStrokePrimitive2D which is used if this try fails
238 bool bIsAntiAliasing
= getOptionsDrawinglayer().IsAntiAliasing();
239 if ( (basegfx::fTools::lessOrEqual(fLineWidth
, 1.0) && bIsAntiAliasing
)
240 || (basegfx::fTools::lessOrEqual(fLineWidth
, 1.5) && !bIsAntiAliasing
))
242 // draw simple hairline
246 bool bHasPoints(false);
247 bool bTryWorked(false);
249 for(sal_uInt32
a(0); a
< aHairLinePolyPolygon
.count(); a
++)
251 const basegfx::B2DPolygon
aSingle(aHairLinePolyPolygon
.getB2DPolygon(a
));
257 if(mpOutputDevice
->DrawPolyLineDirect(
261 rSource
.getLineAttribute().getLineJoin(),
262 rSource
.getLineAttribute().getLineCap(),
263 rSource
.getLineAttribute().getMiterMinimumAngle()
264 /* false bBypassAACheck, default*/))
271 if(!bTryWorked
&& !bHasPoints
)
273 // no geometry despite try
280 bool VclPixelProcessor2D::tryDrawBorderLinePrimitive2DDirect(
281 const drawinglayer::primitive2d::BorderLinePrimitive2D
& rSource
)
283 const basegfx::B2DPoint
& rS
= rSource
.getStart();
284 const basegfx::B2DPoint
& rE
= rSource
.getEnd();
286 double fX1
= rS
.getX();
287 double fY1
= rS
.getY();
288 double fX2
= rE
.getX();
289 double fY2
= rE
.getY();
291 bool bHorizontal
= false;
302 // Neither. Bail out.
305 switch (rSource
.getStyle())
307 case table::BorderLineStyle::SOLID
:
308 case table::BorderLineStyle::DOUBLE_THIN
:
310 const basegfx::BColor aLineColor
=
311 maBColorModifierStack
.getModifiedColor(rSource
.getRGBColorLeft());
312 double nThick
= rtl::math::round(rSource
.getLeftWidth());
314 bool bDouble
= rSource
.getStyle() == table::BorderLineStyle::DOUBLE_THIN
;
316 basegfx::B2DPolygon aTarget
;
320 // Horizontal line. Draw it as a rectangle.
322 aTarget
= makeRectPolygon(fX1
, fY1
, fX2
-fX1
, nThick
);
323 aTarget
.transform(maCurrentTransformation
);
325 basegfx::B2DRange aRange
= aTarget
.getB2DRange();
326 double fH
= aRange
.getHeight();
332 mpOutputDevice
, aRange
.getMinX(), aRange
.getMinY()-1.0, aRange
.getMaxX(), aRange
.getMinY()-1.0,
336 mpOutputDevice
, aRange
.getMinX(), aRange
.getMinY()+1.0, aRange
.getMaxX(), aRange
.getMinY()+1.0,
344 // Draw it as a line.
346 mpOutputDevice
, aRange
.getMinX(), aRange
.getMinY(), aRange
.getMaxX(), aRange
.getMinY(),
352 double fOffset
= rtl::math::round(fH
/2.0, 0, rtl_math_RoundingMode_Down
);
355 // Move it up a bit to align it vertically centered.
356 basegfx::B2DHomMatrix aMat
;
357 aMat
.set(1, 2, -fOffset
);
358 aTarget
.transform(aMat
);
363 // Vertical line. Draw it as a rectangle.
365 aTarget
= makeRectPolygon(fX1
, fY1
, nThick
, fY2
-fY1
);
366 aTarget
.transform(maCurrentTransformation
);
368 basegfx::B2DRange aRange
= aTarget
.getB2DRange();
369 double fW
= aRange
.getWidth();
373 // Draw it as a line.
375 mpOutputDevice
, aRange
.getMinX()-1.0, aRange
.getMinY(), aRange
.getMinX()-1.0, aRange
.getMaxY(),
379 mpOutputDevice
, aRange
.getMinX()+1.0, aRange
.getMinY(), aRange
.getMinX()+1.0, aRange
.getMaxY(),
387 // Draw it as a line.
389 mpOutputDevice
, aRange
.getMinX(), aRange
.getMinY(), aRange
.getMinX(), aRange
.getMaxY(),
395 double fOffset
= rtl::math::round(fW
/2.0, 0, rtl_math_RoundingMode_Down
);
398 // Move it to the left a bit to center it horizontally.
399 basegfx::B2DHomMatrix aMat
;
400 aMat
.set(0, 2, -fOffset
);
401 aTarget
.transform(aMat
);
405 mpOutputDevice
->SetFillColor(Color(aLineColor
));
406 mpOutputDevice
->SetLineColor();
407 mpOutputDevice
->DrawPolygon(aTarget
);
411 case table::BorderLineStyle::DOTTED
:
412 case table::BorderLineStyle::DASHED
:
413 case table::BorderLineStyle::DASH_DOT
:
414 case table::BorderLineStyle::DASH_DOT_DOT
:
415 case table::BorderLineStyle::FINE_DASHED
:
417 std::vector
<double> aPattern
=
418 svtools::GetLineDashing(rSource
.getStyle(), rSource
.getPatternScale()*10.0);
420 if (aPattern
.empty())
421 // Failed to get pattern values.
424 double nThick
= rtl::math::round(rSource
.getLeftWidth());
426 const basegfx::BColor aLineColor
=
427 maBColorModifierStack
.getModifiedColor(rSource
.getRGBColorLeft());
429 // Transform the current line range before using it for rendering.
430 basegfx::B2DRange
aRange(fX1
, fY1
, fX2
, fY2
);
431 aRange
.transform(maCurrentTransformation
);
432 fX1
= aRange
.getMinX();
433 fX2
= aRange
.getMaxX();
434 fY1
= aRange
.getMinY();
435 fY2
= aRange
.getMaxY();
437 basegfx::B2DPolyPolygon aTarget
;
443 if (basegfx::fTools::equalZero(nThick
))
445 // Dash line segment too small to draw. Substitute it with a solid line.
446 drawHairLine(mpOutputDevice
, fX1
, fY1
, fX2
, fY1
, aLineColor
);
450 // Create a dash unit polygon set.
451 basegfx::B2DPolyPolygon aDashes
;
452 std::vector
<double>::const_iterator it
= aPattern
.begin(), itEnd
= aPattern
.end();
453 for (; it
!= itEnd
; ++it
)
454 aDashes
.append(makeRectPolygon(0, 0, *it
, nThick
));
456 aDashes
.transform(maCurrentTransformation
);
457 rtl::math::setNan(&nThick
);
459 // Pixelize the dash unit. We use the same height for
460 // all dash polygons.
461 basegfx::B2DPolyPolygon aDashesPix
;
463 for (sal_uInt32 i
= 0, n
= aDashes
.count(); i
< n
; ++i
)
465 basegfx::B2DPolygon aPoly
= aDashes
.getB2DPolygon(i
);
466 aRange
= aPoly
.getB2DRange();
467 double fW
= rtl::math::round(aRange
.getWidth());
468 if (basegfx::fTools::equalZero(fW
))
470 // Dash line segment too small to draw. Substitute it with a solid line.
471 drawHairLine(mpOutputDevice
, fX1
, fY1
, fX2
, fY1
, aLineColor
);
475 if (rtl::math::isNan(nThick
))
476 nThick
= rtl::math::round(aRange
.getHeight());
478 aDashesPix
.append(makeRectPolygon(0, 0, fW
, nThick
));
481 // Make all dash polygons and render them.
484 sal_uInt32 i
= 0, n
= aDashesPix
.count();
487 basegfx::B2DPolygon aPoly
= aDashesPix
.getB2DPolygon(i
);
488 aRange
= aPoly
.getB2DRange();
491 double fBlockW
= aRange
.getWidth();
492 if (fX
+ fBlockW
> fX2
)
493 // Clip the right end in case it spills over the range.
494 fBlockW
= fX2
- fX
+ 1;
496 double fH
= aRange
.getHeight();
497 if (basegfx::fTools::equalZero(fH
))
500 aTarget
.append(makeRectPolygon(fX
, fY1
, fBlockW
, fH
));
503 bLine
= !bLine
; // line and blank alternate.
504 fX
+= aRange
.getWidth();
511 double fOffset
= rtl::math::round(nThick
/2.0, 0, rtl_math_RoundingMode_Down
);
514 // Move it up a bit to align it vertically centered.
515 basegfx::B2DHomMatrix aMat
;
516 aMat
.set(1, 2, -fOffset
);
517 aTarget
.transform(aMat
);
524 if (basegfx::fTools::equalZero(nThick
))
526 // Dash line segment too small to draw. Substitute it with a solid line.
527 drawHairLine(mpOutputDevice
, fX1
, fY1
, fX1
, fY2
, aLineColor
);
531 // Create a dash unit polygon set.
532 basegfx::B2DPolyPolygon aDashes
;
533 std::vector
<double>::const_iterator it
= aPattern
.begin(), itEnd
= aPattern
.end();
534 for (; it
!= itEnd
; ++it
)
535 aDashes
.append(makeRectPolygon(0, 0, nThick
, *it
));
537 aDashes
.transform(maCurrentTransformation
);
538 rtl::math::setNan(&nThick
);
540 // Pixelize the dash unit. We use the same width for
541 // all dash polygons.
542 basegfx::B2DPolyPolygon aDashesPix
;
544 for (sal_uInt32 i
= 0, n
= aDashes
.count(); i
< n
; ++i
)
546 basegfx::B2DPolygon aPoly
= aDashes
.getB2DPolygon(i
);
547 aRange
= aPoly
.getB2DRange();
548 double fH
= rtl::math::round(aRange
.getHeight());
549 if (basegfx::fTools::equalZero(fH
))
551 // Dash line segment too small to draw. Substitute it with a solid line.
552 drawHairLine(mpOutputDevice
, fX1
, fY1
, fX1
, fY2
, aLineColor
);
556 if (rtl::math::isNan(nThick
))
557 nThick
= rtl::math::round(aRange
.getWidth());
559 aDashesPix
.append(makeRectPolygon(0, 0, nThick
, fH
));
562 // Make all dash polygons and render them.
565 sal_uInt32 i
= 0, n
= aDashesPix
.count();
568 basegfx::B2DPolygon aPoly
= aDashesPix
.getB2DPolygon(i
);
569 aRange
= aPoly
.getB2DRange();
572 double fBlockH
= aRange
.getHeight();
573 if (fY
+ fBlockH
> fY2
)
574 // Clip the bottom end in case it spills over the range.
575 fBlockH
= fY2
- fY
+ 1;
577 double fW
= aRange
.getWidth();
578 if (basegfx::fTools::equalZero(fW
))
581 aTarget
.append(makeRectPolygon(fX1
, fY
, fW
, fBlockH
));
584 bLine
= !bLine
; // line and blank alternate.
585 fY
+= aRange
.getHeight();
592 double fOffset
= rtl::math::round(nThick
/2.0, 0, rtl_math_RoundingMode_Down
);
595 // Move it to the left a bit to center it horizontally.
596 basegfx::B2DHomMatrix aMat
;
597 aMat
.set(0, 2, -fOffset
);
598 aTarget
.transform(aMat
);
602 mpOutputDevice
->SetFillColor(Color(aLineColor
));
603 mpOutputDevice
->SetLineColor();
604 mpOutputDevice
->DrawPolyPolygon(aTarget
);
615 void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D
& rCandidate
)
617 switch(rCandidate
.getPrimitive2DID())
619 case PRIMITIVE2D_ID_WRONGSPELLPRIMITIVE2D
:
621 // directdraw of wrong spell primitive; added test possibility to check wrong spell decompose
622 static bool bHandleWrongSpellDirectly(true);
624 if(bHandleWrongSpellDirectly
)
626 const primitive2d::WrongSpellPrimitive2D
& rWrongSpellPrimitive
= static_cast< const primitive2d::WrongSpellPrimitive2D
& >(rCandidate
);
628 if(!renderWrongSpellPrimitive2D(
629 rWrongSpellPrimitive
,
631 maCurrentTransformation
,
632 maBColorModifierStack
))
634 // fallback to decomposition (MetaFile)
635 process(rWrongSpellPrimitive
.get2DDecomposition(getViewInformation2D()));
640 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
644 case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D
:
646 // directdraw of text simple portion; added test possibility to check text decompose
647 static bool bForceSimpleTextDecomposition(false);
649 // Adapt evtl. used special DrawMode
650 const DrawModeFlags
nOriginalDrawMode(mpOutputDevice
->GetDrawMode());
651 adaptTextToFillDrawMode();
653 if(!bForceSimpleTextDecomposition
&& getOptionsDrawinglayer().IsRenderSimpleTextDirect())
655 RenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D
& >(rCandidate
));
659 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
663 mpOutputDevice
->SetDrawMode(nOriginalDrawMode
);
667 case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D
:
669 // directdraw of decorated text portion; added test possibility to check text decompose
670 static bool bForceComplexTextDecomposition(false);
672 // Adapt evtl. used special DrawMode
673 const DrawModeFlags
nOriginalDrawMode(mpOutputDevice
->GetDrawMode());
674 adaptTextToFillDrawMode();
676 if(!bForceComplexTextDecomposition
&& getOptionsDrawinglayer().IsRenderDecoratedTextDirect())
678 RenderTextSimpleOrDecoratedPortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D
& >(rCandidate
));
682 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
686 mpOutputDevice
->SetDrawMode(nOriginalDrawMode
);
690 case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
:
692 // try to use directly
693 const primitive2d::PolygonHairlinePrimitive2D
& rPolygonHairlinePrimitive2D
= static_cast< const primitive2d::PolygonHairlinePrimitive2D
& >(rCandidate
);
694 static bool bAllowed(true);
696 if(bAllowed
&& tryDrawPolygonHairlinePrimitive2DDirect(rPolygonHairlinePrimitive2D
, 0.0))
701 // direct draw of hairline
702 RenderPolygonHairlinePrimitive2D(rPolygonHairlinePrimitive2D
, true);
705 case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D
:
707 // direct draw of transformed BitmapEx primitive
708 const primitive2d::BitmapPrimitive2D
& rBitmapCandidate
= static_cast< const primitive2d::BitmapPrimitive2D
& >(rCandidate
);
710 // check if graphic content is inside discrete local ViewPort
711 const basegfx::B2DRange
& rDiscreteViewPort(getViewInformation2D().getDiscreteViewport());
712 const basegfx::B2DHomMatrix
aLocalTransform(maCurrentTransformation
* rBitmapCandidate
.getTransform());
714 if(!rDiscreteViewPort
.isEmpty())
716 basegfx::B2DRange
aUnitRange(0.0, 0.0, 1.0, 1.0);
718 aUnitRange
.transform(aLocalTransform
);
720 if(!aUnitRange
.overlaps(rDiscreteViewPort
))
722 // content is outside discrete local ViewPort
727 RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D
& >(rCandidate
));
730 case PRIMITIVE2D_ID_FILLGRAPHICPRIMITIVE2D
:
732 // direct draw of fillBitmapPrimitive
733 RenderFillGraphicPrimitive2D(static_cast< const primitive2d::FillGraphicPrimitive2D
& >(rCandidate
));
736 case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D
:
738 // direct draw of gradient
739 const primitive2d::PolyPolygonGradientPrimitive2D
& rPolygonCandidate
= static_cast< const primitive2d::PolyPolygonGradientPrimitive2D
& >(rCandidate
);
740 const attribute::FillGradientAttribute
& rGradient(rPolygonCandidate
.getFillGradient());
741 basegfx::BColor
aStartColor(maBColorModifierStack
.getModifiedColor(rGradient
.getStartColor()));
742 basegfx::BColor
aEndColor(maBColorModifierStack
.getModifiedColor(rGradient
.getEndColor()));
743 basegfx::B2DPolyPolygon
aLocalPolyPolygon(rPolygonCandidate
.getB2DPolyPolygon());
745 if(aLocalPolyPolygon
.count())
747 aLocalPolyPolygon
.transform(maCurrentTransformation
);
749 if(aStartColor
== aEndColor
)
751 // no gradient at all, draw as polygon in AA and non-AA case
752 mpOutputDevice
->SetLineColor();
753 mpOutputDevice
->SetFillColor(Color(aStartColor
));
754 mpOutputDevice
->DrawPolyPolygon(aLocalPolyPolygon
);
758 // use the primitive decomposition of the metafile
759 process(rPolygonCandidate
.get2DDecomposition(getViewInformation2D()));
764 case PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D
:
766 // direct draw of bitmap
767 RenderPolyPolygonGraphicPrimitive2D(static_cast< const primitive2d::PolyPolygonGraphicPrimitive2D
& >(rCandidate
));
770 case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D
:
772 // try to use directly
773 const primitive2d::PolyPolygonColorPrimitive2D
& rPolyPolygonColorPrimitive2D
= static_cast< const primitive2d::PolyPolygonColorPrimitive2D
& >(rCandidate
);
774 basegfx::B2DPolyPolygon aLocalPolyPolygon
;
775 static bool bAllowed(true);
777 if(bAllowed
&& tryDrawPolyPolygonColorPrimitive2DDirect(rPolyPolygonColorPrimitive2D
, 0.0))
779 // okay, done. In this case no gaps should have to be repaired, too
783 // direct draw of tools::PolyPolygon with color
784 const basegfx::BColor
aPolygonColor(maBColorModifierStack
.getModifiedColor(rPolyPolygonColorPrimitive2D
.getBColor()));
786 mpOutputDevice
->SetFillColor(Color(aPolygonColor
));
787 mpOutputDevice
->SetLineColor();
788 aLocalPolyPolygon
= rPolyPolygonColorPrimitive2D
.getB2DPolyPolygon();
789 aLocalPolyPolygon
.transform(maCurrentTransformation
);
790 mpOutputDevice
->DrawPolyPolygon(aLocalPolyPolygon
);
793 // when AA is on and this filled polygons are the result of stroked line geometry,
794 // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons
795 // Caution: This is needed in both cases (!)
796 if(mnPolygonStrokePrimitive2D
797 && getOptionsDrawinglayer().IsAntiAliasing()
798 && (mpOutputDevice
->GetAntialiasing() & AntialiasingFlags::EnableB2dDraw
))
800 const basegfx::BColor
aPolygonColor(maBColorModifierStack
.getModifiedColor(rPolyPolygonColorPrimitive2D
.getBColor()));
801 sal_uInt32
nCount(aLocalPolyPolygon
.count());
805 aLocalPolyPolygon
= rPolyPolygonColorPrimitive2D
.getB2DPolyPolygon();
806 aLocalPolyPolygon
.transform(maCurrentTransformation
);
807 nCount
= aLocalPolyPolygon
.count();
810 mpOutputDevice
->SetFillColor();
811 mpOutputDevice
->SetLineColor(Color(aPolygonColor
));
813 for(sal_uInt32
a(0); a
< nCount
; a
++)
815 mpOutputDevice
->DrawPolyLine(aLocalPolyPolygon
.getB2DPolygon(a
), 0.0);
821 case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D
:
824 const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
825 const AntialiasingFlags
nOldAntiAliase(mpOutputDevice
->GetAntialiasing());
829 mpOutputDevice
->SetAntialiasing(nOldAntiAliase
| AntialiasingFlags::PixelSnapHairline
);
832 const primitive2d::MetafilePrimitive2D
& rMetafilePrimitive( static_cast< const primitive2d::MetafilePrimitive2D
& >(rCandidate
) );
834 static bool bTestMetaFilePrimitiveDecomposition( true );
835 if( bTestMetaFilePrimitiveDecomposition
&& !rMetafilePrimitive
.getMetaFile().GetUseCanvas() )
837 // use new Metafile decomposition
838 // TODO EMF+ stuffed into METACOMMENT support required
839 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
843 // direct draw of MetaFile
844 RenderMetafilePrimitive2D( rMetafilePrimitive
);
849 mpOutputDevice
->SetAntialiasing(nOldAntiAliase
);
854 case PRIMITIVE2D_ID_MASKPRIMITIVE2D
:
857 RenderMaskPrimitive2DPixel(static_cast< const primitive2d::MaskPrimitive2D
& >(rCandidate
));
860 case PRIMITIVE2D_ID_MODIFIEDCOLORPRIMITIVE2D
:
862 // modified color group. Force output to unified color.
863 RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D
& >(rCandidate
));
866 case PRIMITIVE2D_ID_UNIFIEDTRANSPARENCEPRIMITIVE2D
:
868 // Detect if a single PolyPolygonColorPrimitive2D is contained; in that case,
869 // use the faster OutputDevice::DrawTransparent method
870 const primitive2d::UnifiedTransparencePrimitive2D
& rUniTransparenceCandidate
= static_cast< const primitive2d::UnifiedTransparencePrimitive2D
& >(rCandidate
);
871 const primitive2d::Primitive2DContainer
& rContent
= rUniTransparenceCandidate
.getChildren();
873 if(!rContent
.empty())
875 if(0.0 == rUniTransparenceCandidate
.getTransparence())
877 // not transparent at all, use content
878 process(rUniTransparenceCandidate
.getChildren());
880 else if(rUniTransparenceCandidate
.getTransparence() > 0.0 && rUniTransparenceCandidate
.getTransparence() < 1.0)
882 bool bDrawTransparentUsed(false);
884 // since DEV300 m33 DrawTransparent is supported in VCL (for some targets
885 // natively), so i am now enabling this shortcut
886 static bool bAllowUsingDrawTransparent(true);
888 if(bAllowUsingDrawTransparent
&& 1 == rContent
.size())
890 const primitive2d::Primitive2DReference
xReference(rContent
[0]);
891 const primitive2d::BasePrimitive2D
* pBasePrimitive
= dynamic_cast< const primitive2d::BasePrimitive2D
* >(xReference
.get());
895 switch(pBasePrimitive
->getPrimitive2DID())
897 case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D
:
899 // single transparent tools::PolyPolygon identified, use directly
900 const primitive2d::PolyPolygonColorPrimitive2D
* pPoPoColor
= static_cast< const primitive2d::PolyPolygonColorPrimitive2D
* >(pBasePrimitive
);
901 OSL_ENSURE(pPoPoColor
, "OOps, PrimitiveID and PrimitiveType do not match (!)");
902 bDrawTransparentUsed
= tryDrawPolyPolygonColorPrimitive2DDirect(*pPoPoColor
, rUniTransparenceCandidate
.getTransparence());
905 case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D
:
907 // single transparent PolygonHairlinePrimitive2D identified, use directly
908 const primitive2d::PolygonHairlinePrimitive2D
* pPoHair
= static_cast< const primitive2d::PolygonHairlinePrimitive2D
* >(pBasePrimitive
);
909 OSL_ENSURE(pPoHair
, "OOps, PrimitiveID and PrimitiveType do not match (!)");
911 // do no tallow by default - problem is that self-overlapping parts of this geometry will
912 // not be in a all-same transparency but will already alpha-cover themselves with blending.
913 // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
914 // content to be uniformely transparent.
915 // For hairline the effect is pretty minimal, but still not correct.
916 static bool bAllowed(false);
918 bDrawTransparentUsed
= bAllowed
&& tryDrawPolygonHairlinePrimitive2DDirect(*pPoHair
, rUniTransparenceCandidate
.getTransparence());
921 case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
:
923 // single transparent PolygonStrokePrimitive2D identified, use directly
924 const primitive2d::PolygonStrokePrimitive2D
* pPoStroke
= static_cast< const primitive2d::PolygonStrokePrimitive2D
* >(pBasePrimitive
);
925 OSL_ENSURE(pPoStroke
, "OOps, PrimitiveID and PrimitiveType do not match (!)");
927 // do no tallow by default - problem is that self-overlapping parts of this geometry will
928 // not be in a all-same transparency but will already alpha-cover themselves with blending.
929 // This is not what the UnifiedTransparencePrimitive2D defines: It requires all its
930 // content to be uniformely transparent.
931 // To check, activate and draw a wide transparent self-crossing line/curve
932 static bool bAllowed(false);
934 bDrawTransparentUsed
= bAllowed
&& tryDrawPolygonStrokePrimitive2DDirect(*pPoStroke
, rUniTransparenceCandidate
.getTransparence());
938 SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(rCandidate
.getPrimitive2DID()));
944 if(!bDrawTransparentUsed
)
946 // unified sub-transparence. Draw to VDev first.
947 RenderUnifiedTransparencePrimitive2D(rUniTransparenceCandidate
);
954 case PRIMITIVE2D_ID_TRANSPARENCEPRIMITIVE2D
:
956 // sub-transparence group. Draw to VDev first.
957 RenderTransparencePrimitive2D(static_cast< const primitive2d::TransparencePrimitive2D
& >(rCandidate
));
960 case PRIMITIVE2D_ID_TRANSFORMPRIMITIVE2D
:
963 RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D
& >(rCandidate
));
966 case PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D
:
968 // new XDrawPage for ViewInformation2D
969 RenderPagePreviewPrimitive2D(static_cast< const primitive2d::PagePreviewPrimitive2D
& >(rCandidate
));
972 case PRIMITIVE2D_ID_MARKERARRAYPRIMITIVE2D
:
975 RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D
& >(rCandidate
));
978 case PRIMITIVE2D_ID_POINTARRAYPRIMITIVE2D
:
981 RenderPointArrayPrimitive2D(static_cast< const primitive2d::PointArrayPrimitive2D
& >(rCandidate
));
984 case PRIMITIVE2D_ID_CONTROLPRIMITIVE2D
:
987 const primitive2d::ControlPrimitive2D
& rControlPrimitive
= static_cast< const primitive2d::ControlPrimitive2D
& >(rCandidate
);
988 const uno::Reference
< awt::XControl
>& rXControl(rControlPrimitive
.getXControl());
992 // remember old graphics and create new
993 uno::Reference
< awt::XView
> xControlView(rXControl
, uno::UNO_QUERY_THROW
);
994 const uno::Reference
< awt::XGraphics
> xOriginalGraphics(xControlView
->getGraphics());
995 const uno::Reference
< awt::XGraphics
> xNewGraphics(mpOutputDevice
->CreateUnoGraphics());
997 if(xNewGraphics
.is())
999 // link graphics and view
1000 xControlView
->setGraphics(xNewGraphics
);
1003 const basegfx::B2DHomMatrix
aObjectToPixel(maCurrentTransformation
* rControlPrimitive
.getTransform());
1004 const basegfx::B2DPoint
aTopLeftPixel(aObjectToPixel
* basegfx::B2DPoint(0.0, 0.0));
1006 // find out if the control is already visualized as a VCL-ChildWindow. If yes,
1007 // it does not need to be painted at all.
1008 uno::Reference
< awt::XWindow2
> xControlWindow(rXControl
, uno::UNO_QUERY_THROW
);
1009 const bool bControlIsVisibleAsChildWindow(rXControl
->getPeer().is() && xControlWindow
->isVisible());
1011 if(!bControlIsVisibleAsChildWindow
)
1013 // draw it. Do not forget to use the evtl. offsetted origin of the target device,
1014 // e.g. when used with mask/transparence buffer device
1015 const Point
aOrigin(mpOutputDevice
->GetMapMode().GetOrigin());
1017 aOrigin
.X() + basegfx::fround(aTopLeftPixel
.getX()),
1018 aOrigin
.Y() + basegfx::fround(aTopLeftPixel
.getY()));
1021 // restore original graphics
1022 xControlView
->setGraphics(xOriginalGraphics
);
1025 catch(const uno::Exception
&)
1027 // #i116763# removing since there is a good alternative when the xControlView
1028 // is not found and it is allowed to happen
1029 // DBG_UNHANDLED_EXCEPTION();
1031 // process recursively and use the decomposition as Bitmap
1032 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
1037 case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D
:
1039 // try to use directly
1040 const primitive2d::PolygonStrokePrimitive2D
& rPolygonStrokePrimitive2D
= static_cast< const primitive2d::PolygonStrokePrimitive2D
& >(rCandidate
);
1042 if(tryDrawPolygonStrokePrimitive2DDirect(rPolygonStrokePrimitive2D
, 0.0))
1047 // the stroke primitive may be decomposed to filled polygons. To keep
1048 // evtl. set DrawModes aka DrawModeFlags::BlackLine, DrawModeFlags::GrayLine,
1049 // DrawModeFlags::GhostedLine, DrawModeFlags::WhiteLine or DrawModeFlags::SettingsLine
1050 // working, these need to be copied to the corresponding fill modes
1051 const DrawModeFlags
nOriginalDrawMode(mpOutputDevice
->GetDrawMode());
1052 adaptLineToFillDrawMode();
1054 // polygon stroke primitive
1055 static bool bSuppressFatToHairlineCorrection(false);
1057 if(bSuppressFatToHairlineCorrection
)
1059 // remember that we enter a PolygonStrokePrimitive2D decomposition,
1060 // used for AA thick line drawing
1061 mnPolygonStrokePrimitive2D
++;
1063 // with AA there is no need to handle thin lines special
1064 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
1066 // leave PolygonStrokePrimitive2D
1067 mnPolygonStrokePrimitive2D
--;
1071 // Lines with 1 and 2 pixel width without AA need special treatment since their vsiualisation
1072 // as filled polygons is geometrically correct but looks wrong since polygon filling avoids
1073 // the right and bottom pixels. The used method evaluates that and takes the correct action,
1074 // including calling recursively with decomposition if line is wide enough
1075 RenderPolygonStrokePrimitive2D(rPolygonStrokePrimitive2D
);
1079 mpOutputDevice
->SetDrawMode(nOriginalDrawMode
);
1083 case PRIMITIVE2D_ID_FILLHATCHPRIMITIVE2D
:
1085 static bool bForceIgnoreHatchSmoothing(false);
1087 if(bForceIgnoreHatchSmoothing
|| getOptionsDrawinglayer().IsAntiAliasing())
1089 // if AA is used (or ignore smoothing is on), there is no need to smooth
1090 // hatch painting, use decomposition
1091 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
1095 // without AA, use VCL to draw the hatch. It snaps hatch distances to the next pixel
1096 // and forces hatch distance to be >= 3 pixels to make the hatch display look smoother.
1097 // This is wrong in principle, but looks nicer. This could also be done here directly
1098 // without VCL usage if needed
1099 const primitive2d::FillHatchPrimitive2D
& rFillHatchPrimitive
= static_cast< const primitive2d::FillHatchPrimitive2D
& >(rCandidate
);
1100 const attribute::FillHatchAttribute
& rFillHatchAttributes
= rFillHatchPrimitive
.getFillHatch();
1102 // create hatch polygon in range size and discrete coordinates
1103 basegfx::B2DRange
aHatchRange(rFillHatchPrimitive
.getOutputRange());
1104 aHatchRange
.transform(maCurrentTransformation
);
1105 const basegfx::B2DPolygon
aHatchPolygon(basegfx::tools::createPolygonFromRect(aHatchRange
));
1107 if(rFillHatchAttributes
.isFillBackground())
1109 // #i111846# background fill is active; draw fill polygon
1110 const basegfx::BColor
aPolygonColor(maBColorModifierStack
.getModifiedColor(rFillHatchPrimitive
.getBColor()));
1112 mpOutputDevice
->SetFillColor(Color(aPolygonColor
));
1113 mpOutputDevice
->SetLineColor();
1114 mpOutputDevice
->DrawPolygon(aHatchPolygon
);
1117 // set hatch line color
1118 const basegfx::BColor
aHatchColor(maBColorModifierStack
.getModifiedColor(rFillHatchPrimitive
.getBColor()));
1119 mpOutputDevice
->SetFillColor();
1120 mpOutputDevice
->SetLineColor(Color(aHatchColor
));
1123 HatchStyle
eHatchStyle(HATCH_SINGLE
);
1125 switch(rFillHatchAttributes
.getStyle())
1127 default : // HatchStyle::Single
1131 case attribute::HatchStyle::Double
:
1133 eHatchStyle
= HATCH_DOUBLE
;
1136 case attribute::HatchStyle::Triple
:
1138 eHatchStyle
= HATCH_TRIPLE
;
1144 const basegfx::B2DVector
aDiscreteDistance(maCurrentTransformation
* basegfx::B2DVector(rFillHatchAttributes
.getDistance(), 0.0));
1145 const sal_uInt32
nDistance(basegfx::fround(aDiscreteDistance
.getLength()));
1146 const sal_uInt16
nAngle10((sal_uInt16
)basegfx::fround(rFillHatchAttributes
.getAngle() / F_PI1800
));
1147 ::Hatch
aVCLHatch(eHatchStyle
, Color(rFillHatchAttributes
.getColor()), nDistance
, nAngle10
);
1149 // draw hatch using VCL
1150 mpOutputDevice
->DrawHatch(::tools::PolyPolygon(::tools::Polygon(aHatchPolygon
)), aVCLHatch
);
1154 case PRIMITIVE2D_ID_BACKGROUNDCOLORPRIMITIVE2D
:
1156 // #i98404# Handle directly, especially when AA is active
1157 const primitive2d::BackgroundColorPrimitive2D
& rPrimitive
= static_cast< const primitive2d::BackgroundColorPrimitive2D
& >(rCandidate
);
1158 const AntialiasingFlags
nOriginalAA(mpOutputDevice
->GetAntialiasing());
1160 // switch AA off in all cases
1161 mpOutputDevice
->SetAntialiasing(mpOutputDevice
->GetAntialiasing() & ~AntialiasingFlags::EnableB2dDraw
);
1163 // create color for fill
1164 const basegfx::BColor
aPolygonColor(maBColorModifierStack
.getModifiedColor(rPrimitive
.getBColor()));
1165 Color
aFillColor(aPolygonColor
);
1166 aFillColor
.SetTransparency(sal_uInt8((rPrimitive
.getTransparency() * 255.0) + 0.5));
1167 mpOutputDevice
->SetFillColor(aFillColor
);
1168 mpOutputDevice
->SetLineColor();
1170 // create rectangle for fill
1171 const basegfx::B2DRange
& aViewport(getViewInformation2D().getDiscreteViewport());
1172 const Rectangle
aRectangle(
1173 (sal_Int32
)floor(aViewport
.getMinX()), (sal_Int32
)floor(aViewport
.getMinY()),
1174 (sal_Int32
)ceil(aViewport
.getMaxX()), (sal_Int32
)ceil(aViewport
.getMaxY()));
1175 mpOutputDevice
->DrawRect(aRectangle
);
1177 // restore AA setting
1178 mpOutputDevice
->SetAntialiasing(nOriginalAA
);
1181 case PRIMITIVE2D_ID_TEXTHIERARCHYEDITPRIMITIVE2D
:
1184 // This primitive means that the content is derived from an active text edit,
1185 // not from model data itself. Some renderers need to suppress this content, e.g.
1186 // the pixel renderer used for displaying the edit view (like this one). It's
1187 // not to be suppressed by the MetaFile renderers, so that the edited text is
1188 // part of the MetaFile, e.g. needed for presentation previews.
1189 // Action: Ignore here, do nothing.
1192 case PRIMITIVE2D_ID_INVERTPRIMITIVE2D
:
1194 // invert primitive (currently only used for HighContrast fallback for selection in SW and SC).
1195 // (Not true, also used at least for the drawing of dragged column and row boundaries in SC.)
1196 // Set OutDev to XOR and switch AA off (XOR does not work with AA)
1197 mpOutputDevice
->Push();
1198 mpOutputDevice
->SetRasterOp( ROP_XOR
);
1199 const AntialiasingFlags
nAntiAliasing(mpOutputDevice
->GetAntialiasing());
1200 mpOutputDevice
->SetAntialiasing(nAntiAliasing
& ~AntialiasingFlags::EnableB2dDraw
);
1202 // process content recursively
1203 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
1206 mpOutputDevice
->Pop();
1207 mpOutputDevice
->SetAntialiasing(nAntiAliasing
);
1210 case PRIMITIVE2D_ID_EPSPRIMITIVE2D
:
1212 RenderEpsPrimitive2D(static_cast< const primitive2d::EpsPrimitive2D
& >(rCandidate
));
1215 case PRIMITIVE2D_ID_SVGLINEARATOMPRIMITIVE2D
:
1217 RenderSvgLinearAtomPrimitive2D(static_cast< const primitive2d::SvgLinearAtomPrimitive2D
& >(rCandidate
));
1220 case PRIMITIVE2D_ID_SVGRADIALATOMPRIMITIVE2D
:
1222 RenderSvgRadialAtomPrimitive2D(static_cast< const primitive2d::SvgRadialAtomPrimitive2D
& >(rCandidate
));
1225 case PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D
:
1227 // process recursively, but turn off anti-aliasing. Border
1228 // lines are always rectangular, and look horrible when
1229 // the anti-aliasing is enabled.
1230 AntialiasingFlags nAntiAliasing
= mpOutputDevice
->GetAntialiasing();
1231 mpOutputDevice
->SetAntialiasing(nAntiAliasing
& ~AntialiasingFlags::EnableB2dDraw
);
1233 const drawinglayer::primitive2d::BorderLinePrimitive2D
& rBorder
=
1234 static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D
&>(rCandidate
);
1236 if (!tryDrawBorderLinePrimitive2DDirect(rBorder
))
1238 if (rBorder
.getStyle() == table::BorderLineStyle::DOUBLE
)
1239 process(rBorder
.createDecomposition(getViewInformation2D(), true));
1241 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
1244 mpOutputDevice
->SetAntialiasing(nAntiAliasing
);
1249 SAL_INFO("drawinglayer", "default case for " << drawinglayer::primitive2d::idToString(rCandidate
.getPrimitive2DID()));
1250 // process recursively
1251 process(rCandidate
.get2DDecomposition(getViewInformation2D()));
1256 } // end of namespace processor2d
1257 } // end of namespace drawinglayer
1259 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */