1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: vclprocessor2d.cxx,v $
7 * The Contents of this file are made available subject to
8 * the terms of GNU Lesser General Public License Version 2.1.
11 * GNU Lesser General Public License Version 2.1
12 * =============================================
13 * Copyright 2005 by Sun Microsystems, Inc.
14 * 901 San Antonio Road, Palo Alto, CA 94303, USA
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License version 2.1, as published by the Free Software Foundation.
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 ************************************************************************/
32 // MARKER(update_precomp.py): autogen include statement, do not remove
33 #include "precompiled_drawinglayer.hxx"
35 #include <drawinglayer/processor2d/vclprocessor2d.hxx>
36 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
37 #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
38 #include <tools/debug.hxx>
39 #include <vcl/outdev.hxx>
40 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
41 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
42 #include <vclhelperbitmaptransform.hxx>
43 #include <basegfx/polygon/b2dpolygontools.hxx>
44 #include <vclhelperbitmaprender.hxx>
45 #include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
46 #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
47 #include <drawinglayer/attribute/fillattribute.hxx>
48 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
49 #include <vclhelpergradient.hxx>
50 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
51 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
52 #include <basegfx/polygon/b2dpolypolygontools.hxx>
53 #include <vclhelperbufferdevice.hxx>
54 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
55 #include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx>
56 #include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
57 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
58 #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
59 #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
60 #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
61 #include <svtools/ctloptions.hxx>
62 #include <vcl/svapp.hxx>
63 #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
64 #include <tools/diagnose_ex.h>
65 #include <vcl/metric.hxx>
67 //////////////////////////////////////////////////////////////////////////////
70 #include <com/sun/star/awt/XWindow2.hpp>
71 #include <com/sun/star/awt/PosSize.hpp>
72 #include <com/sun/star/awt/XView.hpp>
73 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
74 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
76 //////////////////////////////////////////////////////////////////////////////
77 // for test, can be removed again
79 #include <basegfx/polygon/b2dpolygonclipper.hxx>
81 //////////////////////////////////////////////////////////////////////////////
83 using namespace com::sun::star
;
85 //////////////////////////////////////////////////////////////////////////////
87 namespace drawinglayer
91 //////////////////////////////////////////////////////////////////////////////
93 using ::com::sun::star::uno::Reference
;
94 using ::com::sun::star::uno::UNO_QUERY
;
95 using ::com::sun::star::uno::UNO_QUERY_THROW
;
96 using ::com::sun::star::uno::Exception
;
97 using ::com::sun::star::awt::XView
;
98 using ::com::sun::star::awt::XGraphics
;
99 using ::com::sun::star::awt::XWindow
;
100 using ::com::sun::star::awt::PosSize::POSSIZE
;
102 static FontUnderline
mapTextLineStyle(primitive2d::FontUnderline eLineStyle
)
107 DBG_WARNING1( "DrawingLayer: Unknown text line style attribute (%d)!", eLineStyle
);
109 case primitive2d::FONT_UNDERLINE_NONE
: return UNDERLINE_NONE
;
110 case primitive2d::FONT_UNDERLINE_SINGLE
: return UNDERLINE_SINGLE
;
111 case primitive2d::FONT_UNDERLINE_DOUBLE
: return UNDERLINE_DOUBLE
;
112 case primitive2d::FONT_UNDERLINE_DOTTED
: return UNDERLINE_DOTTED
;
113 case primitive2d::FONT_UNDERLINE_DASH
: return UNDERLINE_DASH
;
114 case primitive2d::FONT_UNDERLINE_LONGDASH
: return UNDERLINE_LONGDASH
;
115 case primitive2d::FONT_UNDERLINE_DASHDOT
: return UNDERLINE_DASHDOT
;
116 case primitive2d::FONT_UNDERLINE_DASHDOTDOT
: return UNDERLINE_DASHDOTDOT
;
117 case primitive2d::FONT_UNDERLINE_SMALLWAVE
: return UNDERLINE_SMALLWAVE
;
118 case primitive2d::FONT_UNDERLINE_WAVE
: return UNDERLINE_WAVE
;
119 case primitive2d::FONT_UNDERLINE_DOUBLEWAVE
: return UNDERLINE_DOUBLEWAVE
;
120 case primitive2d::FONT_UNDERLINE_BOLD
: return UNDERLINE_BOLD
;
121 case primitive2d::FONT_UNDERLINE_BOLDDOTTED
: return UNDERLINE_BOLDDOTTED
;
122 case primitive2d::FONT_UNDERLINE_BOLDDASH
: return UNDERLINE_BOLDDASH
;
123 case primitive2d::FONT_UNDERLINE_BOLDLONGDASH
: return UNDERLINE_LONGDASH
;
124 case primitive2d::FONT_UNDERLINE_BOLDDASHDOT
: return UNDERLINE_BOLDDASHDOT
;
125 case primitive2d::FONT_UNDERLINE_BOLDDASHDOTDOT
:return UNDERLINE_BOLDDASHDOT
;
126 case primitive2d::FONT_UNDERLINE_BOLDWAVE
: return UNDERLINE_BOLDWAVE
;
130 //////////////////////////////////////////////////////////////////////////////
133 // directdraw of text simple portion or decorated portion primitive. When decorated, all the extra
134 // information is translated to VCL parameters and set at the font.
135 // Acceptance is restricted to no shearing and positive scaling in X and Y (no font mirroring
137 void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D
& rTextCandidate
)
139 // decompose matrix to have position and size of text
140 basegfx::B2DHomMatrix
aLocalTransform(maCurrentTransformation
* rTextCandidate
.getTextTransform());
141 basegfx::B2DVector aFontScaling
, aTranslate
;
142 double fRotate
, fShearX
;
143 aLocalTransform
.decompose(aFontScaling
, aTranslate
, fRotate
, fShearX
);
144 bool bPrimitiveAccepted(false);
146 if(basegfx::fTools::equalZero(fShearX
))
148 if(basegfx::fTools::less(aFontScaling
.getX(), 0.0) && basegfx::fTools::less(aFontScaling
.getY(), 0.0))
150 // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
151 // be expressed as rotation by PI. Use this since the Font rendering will not
152 // apply the negative scales in any form
153 aFontScaling
= basegfx::absolute(aFontScaling
);
157 if(basegfx::fTools::more(aFontScaling
.getX(), 0.0) && basegfx::fTools::more(aFontScaling
.getY(), 0.0))
159 // Get the VCL font (use FontHeight as FontWidth)
160 Font
aFont(primitive2d::getVclFontFromFontAttributes(
161 rTextCandidate
.getFontAttributes(),
165 rTextCandidate
.getLocale()));
167 // handle additional font attributes
168 const primitive2d::TextDecoratedPortionPrimitive2D
* pTCPP
=
169 dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D
*>( &rTextCandidate
);
174 // set the color of text decorations
175 const basegfx::BColor aTextlineColor
= maBColorModifierStack
.getModifiedColor(pTCPP
->getTextlineColor());
176 mpOutputDevice
->SetTextLineColor( Color(aTextlineColor
) );
178 // set Overline attribute
179 FontUnderline eFontOverline
= mapTextLineStyle( pTCPP
->getFontOverline() );
180 if( eFontOverline
!= UNDERLINE_NONE
)
182 aFont
.SetOverline( eFontOverline
);
183 const basegfx::BColor aOverlineColor
= maBColorModifierStack
.getModifiedColor(pTCPP
->getOverlineColor());
184 mpOutputDevice
->SetOverlineColor( Color(aOverlineColor
) );
185 if( pTCPP
->getWordLineMode() )
186 aFont
.SetWordLineMode( true );
189 // set Underline attribute
190 FontUnderline eFontUnderline
= mapTextLineStyle( pTCPP
->getFontUnderline() );
191 if( eFontUnderline
!= UNDERLINE_NONE
)
193 aFont
.SetUnderline( eFontUnderline
);
194 if( pTCPP
->getWordLineMode() )
195 aFont
.SetWordLineMode( true );
196 //TODO: ??? if( pTCPP->getUnderlineAbove() )
197 // aFont.SetUnderlineAbove( true );
200 // set Strikeout attribute
201 FontStrikeout eFontStrikeout
= STRIKEOUT_NONE
;
202 switch( pTCPP
->getFontStrikeout() )
205 DBG_WARNING1( "DrawingLayer: Unknown strikeout attribute (%d)!", pTCPP
->getFontStrikeout() );
207 case primitive2d::FONT_STRIKEOUT_NONE
: eFontStrikeout
= STRIKEOUT_NONE
; break;
208 case primitive2d::FONT_STRIKEOUT_SINGLE
: eFontStrikeout
= STRIKEOUT_SINGLE
; break;
209 case primitive2d::FONT_STRIKEOUT_DOUBLE
: eFontStrikeout
= STRIKEOUT_DOUBLE
; break;
210 case primitive2d::FONT_STRIKEOUT_BOLD
: eFontStrikeout
= STRIKEOUT_BOLD
; break;
211 case primitive2d::FONT_STRIKEOUT_SLASH
: eFontStrikeout
= STRIKEOUT_SLASH
; break;
212 case primitive2d::FONT_STRIKEOUT_X
: eFontStrikeout
= STRIKEOUT_X
; break;
215 if( eFontStrikeout
!= STRIKEOUT_NONE
)
216 aFont
.SetStrikeout( eFontStrikeout
);
218 // set EmphasisMark attribute
219 FontEmphasisMark eFontEmphasisMark
= EMPHASISMARK_NONE
;
220 switch( pTCPP
->getFontEmphasisMark() )
223 DBG_WARNING1( "DrawingLayer: Unknown EmphasisMark style (%d)!", pTCPP
->getFontEmphasisMark() );
225 case primitive2d::FONT_EMPHASISMARK_NONE
: eFontEmphasisMark
= EMPHASISMARK_NONE
; break;
226 case primitive2d::FONT_EMPHASISMARK_DOT
: eFontEmphasisMark
= EMPHASISMARK_DOT
; break;
227 case primitive2d::FONT_EMPHASISMARK_CIRCLE
: eFontEmphasisMark
= EMPHASISMARK_CIRCLE
; break;
228 case primitive2d::FONT_EMPHASISMARK_DISC
: eFontEmphasisMark
= EMPHASISMARK_DISC
; break;
229 case primitive2d::FONT_EMPHASISMARK_ACCENT
: eFontEmphasisMark
= EMPHASISMARK_ACCENT
; break;
232 if( eFontEmphasisMark
!= EMPHASISMARK_NONE
)
234 DBG_ASSERT( (pTCPP
->getEmphasisMarkAbove() != pTCPP
->getEmphasisMarkBelow()),
235 "DrawingLayer: Bad EmphasisMark position!" );
236 if( pTCPP
->getEmphasisMarkAbove() )
237 eFontEmphasisMark
|= EMPHASISMARK_POS_ABOVE
;
239 eFontEmphasisMark
|= EMPHASISMARK_POS_BELOW
;
240 aFont
.SetEmphasisMark( eFontEmphasisMark
);
243 // set Relief attribute
244 FontRelief eFontRelief
= RELIEF_NONE
;
245 switch( pTCPP
->getFontRelief() )
248 DBG_WARNING1( "DrawingLayer: Unknown Relief style (%d)!", pTCPP
->getFontRelief() );
250 case primitive2d::FONT_RELIEF_NONE
: eFontRelief
= RELIEF_NONE
; break;
251 case primitive2d::FONT_RELIEF_EMBOSSED
: eFontRelief
= RELIEF_EMBOSSED
; break;
252 case primitive2d::FONT_RELIEF_ENGRAVED
: eFontRelief
= RELIEF_ENGRAVED
; break;
255 if( eFontRelief
!= RELIEF_NONE
)
256 aFont
.SetRelief( eFontRelief
);
258 // set Shadow attribute
259 if( pTCPP
->getShadow() )
260 aFont
.SetShadow( true );
263 // create transformed integer DXArray in view coordinate system
264 ::std::vector
< sal_Int32
> aTransformedDXArray
;
266 if(rTextCandidate
.getDXArray().size())
268 aTransformedDXArray
.reserve(rTextCandidate
.getDXArray().size());
269 const basegfx::B2DVector
aPixelVector(maCurrentTransformation
* basegfx::B2DVector(1.0, 0.0));
270 const double fPixelVectorFactor(aPixelVector
.getLength());
272 for(::std::vector
< double >::const_iterator
aStart(rTextCandidate
.getDXArray().begin());
273 aStart
!= rTextCandidate
.getDXArray().end(); aStart
++)
275 aTransformedDXArray
.push_back(basegfx::fround((*aStart
) * fPixelVectorFactor
));
279 // set parameters and paint text snippet
280 const basegfx::BColor
aRGBFontColor(maBColorModifierStack
.getModifiedColor(rTextCandidate
.getFontColor()));
281 const basegfx::B2DPoint
aPoint(aLocalTransform
* basegfx::B2DPoint(0.0, 0.0));
282 const Point
aStartPoint(basegfx::fround(aPoint
.getX()), basegfx::fround(aPoint
.getY()));
283 const sal_uInt32
nOldLayoutMode(mpOutputDevice
->GetLayoutMode());
285 if(rTextCandidate
.getFontAttributes().getRTL())
287 sal_uInt32
nRTLLayoutMode(nOldLayoutMode
& ~(TEXT_LAYOUT_COMPLEX_DISABLED
|TEXT_LAYOUT_BIDI_STRONG
));
288 nRTLLayoutMode
|= TEXT_LAYOUT_BIDI_RTL
|TEXT_LAYOUT_TEXTORIGIN_LEFT
;
289 mpOutputDevice
->SetLayoutMode(nRTLLayoutMode
);
292 mpOutputDevice
->SetFont(aFont
);
293 mpOutputDevice
->SetTextColor(Color(aRGBFontColor
));
295 if(aTransformedDXArray
.size())
297 mpOutputDevice
->DrawTextArray(
299 rTextCandidate
.getText(),
300 &(aTransformedDXArray
[0]),
301 rTextCandidate
.getTextPosition(),
302 rTextCandidate
.getTextLength());
306 mpOutputDevice
->DrawText(
308 rTextCandidate
.getText(),
309 rTextCandidate
.getTextPosition(),
310 rTextCandidate
.getTextLength());
313 if(rTextCandidate
.getFontAttributes().getRTL())
315 mpOutputDevice
->SetLayoutMode(nOldLayoutMode
);
318 bPrimitiveAccepted
= true;
322 if(!bPrimitiveAccepted
)
325 process(rTextCandidate
.get2DDecomposition(getViewInformation2D()));
329 // direct draw of hairline
330 void VclProcessor2D::RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D
& rPolygonCandidate
, bool bPixelBased
)
332 const basegfx::BColor
aHairlineColor(maBColorModifierStack
.getModifiedColor(rPolygonCandidate
.getBColor()));
333 mpOutputDevice
->SetLineColor(Color(aHairlineColor
));
334 mpOutputDevice
->SetFillColor();
336 basegfx::B2DPolygon
aLocalPolygon(rPolygonCandidate
.getB2DPolygon());
337 aLocalPolygon
.transform(maCurrentTransformation
);
339 if(bPixelBased
&& getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete())
342 // when a Hairline is painted and AntiAliasing is on the option SnapHorVerLinesToDiscrete
343 // allows to suppress AntiAliasing for pure horizontal or vertical lines. This is done since
344 // not-AntiAliased such lines look more pleasing to the eye (e.g. 2D chart content). This
345 // NEEDS to be done in discrete coordinates, so only useful for pixel based rendering.
346 aLocalPolygon
= basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aLocalPolygon
);
349 mpOutputDevice
->DrawPolyLine(aLocalPolygon
, 0.0);
352 // direct draw of transformed BitmapEx primitive
353 void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D
& rBitmapCandidate
)
355 // create local transform
356 basegfx::B2DHomMatrix
aLocalTransform(maCurrentTransformation
* rBitmapCandidate
.getTransform());
357 BitmapEx
aBitmapEx(rBitmapCandidate
.getBitmapEx());
358 bool bPainted(false);
360 if(maBColorModifierStack
.count())
362 aBitmapEx
= impModifyBitmapEx(maBColorModifierStack
, aBitmapEx
);
364 if(aBitmapEx
.IsEmpty())
366 // color gets completely replaced, get it
367 const basegfx::BColor
aModifiedColor(maBColorModifierStack
.getModifiedColor(basegfx::BColor()));
368 basegfx::B2DPolygon
aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
369 aPolygon
.transform(aLocalTransform
);
371 mpOutputDevice
->SetFillColor(Color(aModifiedColor
));
372 mpOutputDevice
->SetLineColor();
373 mpOutputDevice
->DrawPolygon(aPolygon
);
381 static bool bForceUseOfOwnTransformer(false);
382 static bool bUseGraphicManager(true);
384 // decompose matrix to check for shear, rotate and mirroring
385 basegfx::B2DVector aScale
, aTranslate
;
386 double fRotate
, fShearX
;
387 aLocalTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
389 if(!bForceUseOfOwnTransformer
&& basegfx::fTools::equalZero(fShearX
))
391 if(!bUseGraphicManager
&& basegfx::fTools::equalZero(fRotate
))
393 RenderBitmapPrimitive2D_BitmapEx(*mpOutputDevice
, aBitmapEx
, aLocalTransform
);
397 RenderBitmapPrimitive2D_GraphicManager(*mpOutputDevice
, aBitmapEx
, aLocalTransform
);
402 if(!aBitmapEx
.IsTransparent() && (!basegfx::fTools::equalZero(fShearX
) || !basegfx::fTools::equalZero(fRotate
)))
404 // parts will be uncovered, extend aBitmapEx with a mask bitmap
405 const Bitmap
aContent(aBitmapEx
.GetBitmap());
406 aBitmapEx
= BitmapEx(aContent
, Bitmap(aContent
.GetSizePixel(), 1));
409 RenderBitmapPrimitive2D_self(*mpOutputDevice
, aBitmapEx
, aLocalTransform
);
414 void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D
& rFillBitmapCandidate
)
416 const attribute::FillBitmapAttribute
& rFillBitmapAttribute(rFillBitmapCandidate
.getFillBitmap());
417 bool bPrimitiveAccepted(false);
419 if(rFillBitmapAttribute
.getTiling())
421 // decompose matrix to check for shear, rotate and mirroring
422 basegfx::B2DHomMatrix
aLocalTransform(maCurrentTransformation
* rFillBitmapCandidate
.getTransformation());
423 basegfx::B2DVector aScale
, aTranslate
;
424 double fRotate
, fShearX
;
425 aLocalTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
427 if(basegfx::fTools::equalZero(fRotate
) && basegfx::fTools::equalZero(fShearX
))
429 // no shear or rotate, draw direct in pixel coordinates
430 bPrimitiveAccepted
= true;
431 BitmapEx
aBitmapEx(rFillBitmapAttribute
.getBitmap());
432 bool bPainted(false);
434 if(maBColorModifierStack
.count())
436 aBitmapEx
= impModifyBitmapEx(maBColorModifierStack
, aBitmapEx
);
438 if(aBitmapEx
.IsEmpty())
440 // color gets completely replaced, get it
441 const basegfx::BColor
aModifiedColor(maBColorModifierStack
.getModifiedColor(basegfx::BColor()));
442 basegfx::B2DPolygon
aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
443 aPolygon
.transform(aLocalTransform
);
445 mpOutputDevice
->SetFillColor(Color(aModifiedColor
));
446 mpOutputDevice
->SetLineColor();
447 mpOutputDevice
->DrawPolygon(aPolygon
);
455 const basegfx::B2DPoint
aObjTopLeft(aTranslate
.getX(), aTranslate
.getY());
456 const basegfx::B2DPoint
aObjBottomRight(aTranslate
.getX() + aScale
.getX(), aTranslate
.getY() + aScale
.getY());
457 const Point
aObjTL(mpOutputDevice
->LogicToPixel(Point((sal_Int32
)aObjTopLeft
.getX(), (sal_Int32
)aObjTopLeft
.getY())));
458 const Point
aObjBR(mpOutputDevice
->LogicToPixel(Point((sal_Int32
)aObjBottomRight
.getX(), (sal_Int32
)aObjBottomRight
.getY())));
460 const basegfx::B2DPoint
aBmpTopLeft(aLocalTransform
* rFillBitmapAttribute
.getTopLeft());
461 const basegfx::B2DPoint
aBmpBottomRight(aLocalTransform
* basegfx::B2DPoint(rFillBitmapAttribute
.getTopLeft() + rFillBitmapAttribute
.getSize()));
462 const Point
aBmpTL(mpOutputDevice
->LogicToPixel(Point((sal_Int32
)aBmpTopLeft
.getX(), (sal_Int32
)aBmpTopLeft
.getY())));
463 const Point
aBmpBR(mpOutputDevice
->LogicToPixel(Point((sal_Int32
)aBmpBottomRight
.getX(), (sal_Int32
)aBmpBottomRight
.getY())));
465 sal_Int32
nOWidth(aObjBR
.X() - aObjTL
.X());
466 sal_Int32
nOHeight(aObjBR
.Y() - aObjTL
.Y());
468 // only do something when object has a size in discrete units
469 if(nOWidth
> 0 && nOHeight
> 0)
471 sal_Int32
nBWidth(aBmpBR
.X() - aBmpTL
.X());
472 sal_Int32
nBHeight(aBmpBR
.Y() - aBmpTL
.Y());
474 // only do something when bitmap fill has a size in discrete units
475 if(nBWidth
> 0 && nBHeight
> 0)
477 sal_Int32
nBLeft(aBmpTL
.X());
478 sal_Int32
nBTop(aBmpTL
.Y());
480 if(nBLeft
> aObjTL
.X())
482 nBLeft
-= ((nBLeft
/ nBWidth
) + 1L) * nBWidth
;
485 if(nBLeft
+ nBWidth
<= aObjTL
.X())
487 nBLeft
-= (nBLeft
/ nBWidth
) * nBWidth
;
490 if(nBTop
> aObjTL
.Y())
492 nBTop
-= ((nBTop
/ nBHeight
) + 1L) * nBHeight
;
495 if(nBTop
+ nBHeight
<= aObjTL
.Y())
497 nBTop
-= (nBTop
/ nBHeight
) * nBHeight
;
500 // nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it
501 // in vcl many times, create a size-optimized version
502 const Size
aNeededBitmapSizePixel(nBWidth
, nBHeight
);
504 if(aNeededBitmapSizePixel
!= aBitmapEx
.GetSizePixel())
506 aBitmapEx
.Scale(aNeededBitmapSizePixel
);
510 const Point
aEmptyPoint(0, 0);
511 const Rectangle
aVisiblePixel(aEmptyPoint
, mpOutputDevice
->GetOutputSizePixel());
512 const bool bWasEnabled(mpOutputDevice
->IsMapModeEnabled());
513 mpOutputDevice
->EnableMapMode(false);
515 for(sal_Int32
nXPos(nBLeft
); nXPos
< aObjTL
.X() + nOWidth
; nXPos
+= nBWidth
)
517 for(sal_Int32
nYPos(nBTop
); nYPos
< aObjTL
.Y() + nOHeight
; nYPos
+= nBHeight
)
519 const Rectangle
aOutRectPixel(Point(nXPos
, nYPos
), aNeededBitmapSizePixel
);
521 if(aOutRectPixel
.IsOver(aVisiblePixel
))
523 mpOutputDevice
->DrawBitmapEx(aOutRectPixel
.TopLeft(), aBitmapEx
);
529 mpOutputDevice
->EnableMapMode(bWasEnabled
);
536 if(!bPrimitiveAccepted
)
538 // do not accept, use decomposition
539 process(rFillBitmapCandidate
.get2DDecomposition(getViewInformation2D()));
543 // direct draw of gradient
544 void VclProcessor2D::RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D
& rPolygonCandidate
)
546 const attribute::FillGradientAttribute
& rGradient(rPolygonCandidate
.getFillGradient());
547 basegfx::BColor
aStartColor(maBColorModifierStack
.getModifiedColor(rGradient
.getStartColor()));
548 basegfx::BColor
aEndColor(maBColorModifierStack
.getModifiedColor(rGradient
.getEndColor()));
549 basegfx::B2DPolyPolygon
aLocalPolyPolygon(rPolygonCandidate
.getB2DPolyPolygon());
550 aLocalPolyPolygon
.transform(maCurrentTransformation
);
552 if(aStartColor
== aEndColor
)
554 // no gradient at all, draw as polygon
555 mpOutputDevice
->SetLineColor();
556 mpOutputDevice
->SetFillColor(Color(aStartColor
));
557 mpOutputDevice
->DrawPolyPolygon(aLocalPolyPolygon
);
561 impDrawGradientToOutDev(
562 *mpOutputDevice
, aLocalPolyPolygon
, rGradient
.getStyle(), rGradient
.getSteps(),
563 aStartColor
, aEndColor
, rGradient
.getBorder(),
564 -rGradient
.getAngle(), rGradient
.getOffsetX(), rGradient
.getOffsetY(), false);
568 // direct draw of PolyPolygon with color
569 void VclProcessor2D::RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D
& rPolygonCandidate
)
571 const basegfx::BColor
aPolygonColor(maBColorModifierStack
.getModifiedColor(rPolygonCandidate
.getBColor()));
572 mpOutputDevice
->SetFillColor(Color(aPolygonColor
));
573 mpOutputDevice
->SetLineColor();
575 basegfx::B2DPolyPolygon
aLocalPolyPolygon(rPolygonCandidate
.getB2DPolyPolygon());
576 aLocalPolyPolygon
.transform(maCurrentTransformation
);
577 mpOutputDevice
->DrawPolyPolygon(aLocalPolyPolygon
);
579 if(mnPolygonStrokePrimitive2D
&& getOptionsDrawinglayer().IsAntiAliasing())
581 // when AA is on and this filled polygons are the result of stroked line geometry,
582 // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons
583 mpOutputDevice
->SetFillColor();
584 mpOutputDevice
->SetLineColor(Color(aPolygonColor
));
585 const sal_uInt32
nCount(aLocalPolyPolygon
.count());
587 for(sal_uInt32
a(0); a
< nCount
; a
++)
589 mpOutputDevice
->DrawPolyLine(aLocalPolyPolygon
.getB2DPolygon(a
), 0.0);
593 static bool bTestPolygonClipping(false);
594 if(bTestPolygonClipping
)
596 static bool bInside(true);
597 static bool bFilled(false);
598 static bool bLine(false);
600 basegfx::B2DRange
aRange(aLocalPolyPolygon
.getB2DRange());
601 aRange
.grow(aRange
.getWidth() * -0.1);
605 basegfx::B2DPolyPolygon
aFilledClipped(basegfx::tools::clipPolyPolygonOnRange(aLocalPolyPolygon
, aRange
, bInside
, false));
606 basegfx::BColor
aRand(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0);
607 mpOutputDevice
->SetFillColor(Color(aRand
));
608 mpOutputDevice
->SetLineColor();
609 mpOutputDevice
->DrawPolyPolygon(aFilledClipped
);
614 basegfx::B2DPolyPolygon
aLineClipped(basegfx::tools::clipPolyPolygonOnRange(aLocalPolyPolygon
, aRange
, bInside
, true));
615 basegfx::BColor
aRand(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0);
616 mpOutputDevice
->SetFillColor();
617 mpOutputDevice
->SetLineColor(Color(aRand
));
619 for(sal_uInt32
a(0); a
< aLineClipped
.count(); a
++)
621 mpOutputDevice
->DrawPolyLine(aLineClipped
.getB2DPolygon(a
), 0.0);
627 // direct draw of MetaFile
628 void VclProcessor2D::RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D
& rMetaCandidate
)
630 // decompose matrix to check for shear, rotate and mirroring
631 basegfx::B2DHomMatrix
aLocalTransform(maCurrentTransformation
* rMetaCandidate
.getTransform());
632 basegfx::B2DVector aScale
, aTranslate
;
633 double fRotate
, fShearX
;
634 aLocalTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
636 if(basegfx::fTools::less(aScale
.getX(), 0.0) && basegfx::fTools::less(aScale
.getY(), 0.0))
638 // #i102175# handle special case: If scale is negative in (x,y) (3rd quadrant), it can
639 // be expressed as rotation by PI. This needs to be done for Metafiles since
640 // these can be rotated, but not really mirrored
641 aScale
= basegfx::absolute(aScale
);
646 basegfx::B2DRange
aOutlineRange(rMetaCandidate
.getB2DRange(getViewInformation2D()));
647 aOutlineRange
.transform(maCurrentTransformation
);
649 // Due to the integer MapModes used from VCL aind inside MetaFiles errors of up to three
650 // pixels in size may happen. As long as there is no better way (e.g. convert the MetaFile
651 // to primitives) it is necessary to reduce maximum pixel size by 1 in X and Y and to use
652 // the inner pixel bounds accordingly (ceil resp. floor). This will also be done for logic
653 // units e.g. when creating a new MetaFile, but since much huger value ranges are used
654 // there typically will be okay for this compromize.
655 Rectangle
aDestRectView(
656 // !!CAUTION!! Here, ceil and floor are exchanged BY PURPOSE, do NOT copy when
657 // looking for a standard conversion to rectangle (!)
658 (sal_Int32
)ceil(aOutlineRange
.getMinX()), (sal_Int32
)ceil(aOutlineRange
.getMinY()),
659 (sal_Int32
)floor(aOutlineRange
.getMaxX()), (sal_Int32
)floor(aOutlineRange
.getMaxY()));
661 // get metafile (copy it)
662 GDIMetaFile aMetaFile
;
664 if(maBColorModifierStack
.count())
666 const basegfx::BColor
aRGBBaseColor(0, 0, 0);
667 const basegfx::BColor
aRGBColor(maBColorModifierStack
.getModifiedColor(aRGBBaseColor
));
668 aMetaFile
= rMetaCandidate
.getMetaFile().GetMonochromeMtf(Color(aRGBColor
));
672 aMetaFile
= rMetaCandidate
.getMetaFile();
676 if(!basegfx::fTools::equalZero(fRotate
))
679 // MetaFile::Rotate has no input parameter check, so the parameter needs to be
680 // well-aligned to the old range [0..3600] 10th degrees with inverse orientation
681 sal_Int16
nRotation((sal_Int16
)((fRotate
/ F_PI180
) * -10.0));
686 while(nRotation
>= 3600)
689 aMetaFile
.Rotate(nRotation
);
692 // Prepare target output size
693 Size
aDestSize(aDestRectView
.GetSize());
695 if(aDestSize
.getWidth() && aDestSize
.getHeight())
697 // Get preferred Metafile output size. When it's very equal to the output size, it's probably
698 // a rounding error somewhere, so correct it to get a 1:1 output without single pixel scalings
699 // of the Metafile (esp. for contaned Bitmaps, e.g 3D charts)
700 const Size
aPrefSize(mpOutputDevice
->LogicToPixel(aMetaFile
.GetPrefSize(), aMetaFile
.GetPrefMapMode()));
702 if(aPrefSize
.getWidth() && (aPrefSize
.getWidth() - 1 == aDestSize
.getWidth() || aPrefSize
.getWidth() + 1 == aDestSize
.getWidth()))
704 aDestSize
.setWidth(aPrefSize
.getWidth());
707 if(aPrefSize
.getHeight() && (aPrefSize
.getHeight() - 1 == aDestSize
.getHeight() || aPrefSize
.getHeight() + 1 == aDestSize
.getHeight()))
709 aDestSize
.setHeight(aPrefSize
.getHeight());
713 aMetaFile
.WindStart();
714 aMetaFile
.Play(mpOutputDevice
, aDestRectView
.TopLeft(), aDestSize
);
718 // mask group. Force output to VDev and create mask from given mask
719 void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D
& rMaskCandidate
)
721 if(rMaskCandidate
.getChildren().hasElements())
723 basegfx::B2DPolyPolygon
aMask(rMaskCandidate
.getMask());
727 aMask
.transform(maCurrentTransformation
);
728 const basegfx::B2DRange
aRange(basegfx::tools::getRange(aMask
));
729 impBufferDevice
aBufferDevice(*mpOutputDevice
, aRange
, true);
731 if(aBufferDevice
.isVisible())
733 // remember last OutDev and set to content
734 OutputDevice
* pLastOutputDevice
= mpOutputDevice
;
735 mpOutputDevice
= &aBufferDevice
.getContent();
738 process(rMaskCandidate
.getChildren());
740 // back to old OutDev
741 mpOutputDevice
= pLastOutputDevice
;
744 if(getOptionsDrawinglayer().IsAntiAliasing())
746 // with AA, use 8bit AlphaMask to get nice borders
747 VirtualDevice
& rAlpha
= aBufferDevice
.getAlpha();
748 rAlpha
.SetLineColor();
749 rAlpha
.SetFillColor(COL_BLACK
);
750 rAlpha
.DrawPolyPolygon(aMask
);
752 // dump buffer to outdev
753 aBufferDevice
.paint();
757 // No AA, use 1bit mask
758 VirtualDevice
& rMask
= aBufferDevice
.getMask();
759 rMask
.SetLineColor();
760 rMask
.SetFillColor(COL_BLACK
);
761 rMask
.DrawPolyPolygon(aMask
);
763 // dump buffer to outdev
764 aBufferDevice
.paint();
771 // modified color group. Force output to unified color.
772 void VclProcessor2D::RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D
& rModifiedCandidate
)
774 if(rModifiedCandidate
.getChildren().hasElements())
776 maBColorModifierStack
.push(rModifiedCandidate
.getColorModifier());
777 process(rModifiedCandidate
.getChildren());
778 maBColorModifierStack
.pop();
782 // unified sub-transparence. Draw to VDev first.
783 void VclProcessor2D::RenderUnifiedAlphaPrimitive2D(const primitive2d::UnifiedAlphaPrimitive2D
& rTransCandidate
)
785 static bool bForceToDecomposition(false);
787 if(rTransCandidate
.getChildren().hasElements())
789 if(bForceToDecomposition
)
792 process(rTransCandidate
.get2DDecomposition(getViewInformation2D()));
796 if(0.0 == rTransCandidate
.getAlpha())
798 // no transparence used, so just use the content
799 process(rTransCandidate
.getChildren());
801 else if(rTransCandidate
.getAlpha() > 0.0 && rTransCandidate
.getAlpha() < 1.0)
803 // alpha is in visible range
804 basegfx::B2DRange
aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate
.getChildren(), getViewInformation2D()));
805 aRange
.transform(maCurrentTransformation
);
806 impBufferDevice
aBufferDevice(*mpOutputDevice
, aRange
, true);
808 if(aBufferDevice
.isVisible())
810 // remember last OutDev and set to content
811 OutputDevice
* pLastOutputDevice
= mpOutputDevice
;
812 mpOutputDevice
= &aBufferDevice
.getContent();
814 // paint content to it
815 process(rTransCandidate
.getChildren());
817 // back to old OutDev
818 mpOutputDevice
= pLastOutputDevice
;
820 // dump buffer to outdev using given alpha
821 aBufferDevice
.paint(rTransCandidate
.getAlpha());
828 // sub-transparence group. Draw to VDev first.
829 void VclProcessor2D::RenderAlphaPrimitive2D(const primitive2d::AlphaPrimitive2D
& rTransCandidate
)
831 if(rTransCandidate
.getChildren().hasElements())
833 basegfx::B2DRange
aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate
.getChildren(), getViewInformation2D()));
834 aRange
.transform(maCurrentTransformation
);
835 impBufferDevice
aBufferDevice(*mpOutputDevice
, aRange
, true);
837 if(aBufferDevice
.isVisible())
839 // remember last OutDev and set to content
840 OutputDevice
* pLastOutputDevice
= mpOutputDevice
;
841 mpOutputDevice
= &aBufferDevice
.getContent();
843 // paint content to it
844 process(rTransCandidate
.getChildren());
847 mpOutputDevice
= &aBufferDevice
.getAlpha();
849 // when painting alpha masks, reset the color stack
850 basegfx::BColorModifierStack
aLastBColorModifierStack(maBColorModifierStack
);
851 maBColorModifierStack
= basegfx::BColorModifierStack();
853 // paint mask to it (always with alpha intensities, evtl. with AA)
854 process(rTransCandidate
.getAlpha());
856 // back to old color stack
857 maBColorModifierStack
= aLastBColorModifierStack
;
859 // back to old OutDev
860 mpOutputDevice
= pLastOutputDevice
;
862 // dump buffer to outdev
863 aBufferDevice
.paint();
869 void VclProcessor2D::RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D
& rTransformCandidate
)
871 // remember current transformation and ViewInformation
872 const basegfx::B2DHomMatrix
aLastCurrentTransformation(maCurrentTransformation
);
873 const geometry::ViewInformation2D
aLastViewInformation2D(getViewInformation2D());
875 // create new transformations for CurrentTransformation
876 // and for local ViewInformation2D
877 maCurrentTransformation
= maCurrentTransformation
* rTransformCandidate
.getTransformation();
878 const geometry::ViewInformation2D
aViewInformation2D(
879 getViewInformation2D().getObjectTransformation() * rTransformCandidate
.getTransformation(),
880 getViewInformation2D().getViewTransformation(),
881 getViewInformation2D().getViewport(),
882 getViewInformation2D().getVisualizedPage(),
883 getViewInformation2D().getViewTime(),
884 getViewInformation2D().getExtendedInformationSequence());
885 updateViewInformation(aViewInformation2D
);
888 process(rTransformCandidate
.getChildren());
890 // restore transformations
891 maCurrentTransformation
= aLastCurrentTransformation
;
892 updateViewInformation(aLastViewInformation2D
);
895 // new XDrawPage for ViewInformation2D
896 void VclProcessor2D::RenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D
& rPagePreviewCandidate
)
898 // remember current transformation and ViewInformation
899 const geometry::ViewInformation2D
aLastViewInformation2D(getViewInformation2D());
901 // create new local ViewInformation2D
902 const geometry::ViewInformation2D
aViewInformation2D(
903 getViewInformation2D().getObjectTransformation(),
904 getViewInformation2D().getViewTransformation(),
905 getViewInformation2D().getViewport(),
906 rPagePreviewCandidate
.getXDrawPage(),
907 getViewInformation2D().getViewTime(),
908 getViewInformation2D().getExtendedInformationSequence());
909 updateViewInformation(aViewInformation2D
);
911 // proccess decomposed content
912 process(rPagePreviewCandidate
.get2DDecomposition(getViewInformation2D()));
914 // restore transformations
915 updateViewInformation(aLastViewInformation2D
);
919 void VclProcessor2D::RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D
& rMarkArrayCandidate
)
921 static bool bCheckCompleteMarkerDecompose(false);
922 if(bCheckCompleteMarkerDecompose
)
924 process(rMarkArrayCandidate
.get2DDecomposition(getViewInformation2D()));
929 const std::vector
< basegfx::B2DPoint
>& rPositions
= rMarkArrayCandidate
.getPositions();
930 const sal_uInt32
nCount(rPositions
.size());
932 if(nCount
&& !rMarkArrayCandidate
.getMarker().IsEmpty())
935 const BitmapEx
& rMarker(rMarkArrayCandidate
.getMarker());
936 const Size
aBitmapSize(rMarker
.GetSizePixel());
938 if(aBitmapSize
.Width() && aBitmapSize
.Height())
940 // get discrete half size
941 const basegfx::B2DVector
aDiscreteHalfSize(
942 (aBitmapSize
.getWidth() - 1.0) * 0.5,
943 (aBitmapSize
.getHeight() - 1.0) * 0.5);
944 const bool bWasEnabled(mpOutputDevice
->IsMapModeEnabled());
946 // do not forget evtl. moved origin in target device MapMode when
947 // switching it off; it would be missing and lead to wrong positions.
948 // All his could be done using logic sizes and coordinates, too, but
949 // we want a 1:1 bitmap rendering here, so it's more safe and faster
950 // to work with switching off MapMode usage completely.
951 const Point
aOrigin(mpOutputDevice
->GetMapMode().GetOrigin());
953 mpOutputDevice
->EnableMapMode(false);
955 for(std::vector
< basegfx::B2DPoint
>::const_iterator
aIter(rPositions
.begin()); aIter
!= rPositions
.end(); aIter
++)
957 const basegfx::B2DPoint
aDiscreteTopLeft((maCurrentTransformation
* (*aIter
)) - aDiscreteHalfSize
);
958 const Point
aDiscretePoint(basegfx::fround(aDiscreteTopLeft
.getX()), basegfx::fround(aDiscreteTopLeft
.getY()));
960 mpOutputDevice
->DrawBitmapEx(aDiscretePoint
+ aOrigin
, rMarker
);
963 mpOutputDevice
->EnableMapMode(bWasEnabled
);
969 void VclProcessor2D::RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D
& rPointArrayCandidate
)
971 const std::vector
< basegfx::B2DPoint
>& rPositions
= rPointArrayCandidate
.getPositions();
972 const basegfx::BColor
aRGBColor(maBColorModifierStack
.getModifiedColor(rPointArrayCandidate
.getRGBColor()));
973 const Color
aVCLColor(aRGBColor
);
975 for(std::vector
< basegfx::B2DPoint
>::const_iterator
aIter(rPositions
.begin()); aIter
!= rPositions
.end(); aIter
++)
977 const basegfx::B2DPoint
aViewPosition(maCurrentTransformation
* (*aIter
));
978 const Point
aPos(basegfx::fround(aViewPosition
.getX()), basegfx::fround(aViewPosition
.getY()));
980 mpOutputDevice
->DrawPixel(aPos
, aVCLColor
);
984 void VclProcessor2D::RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D
& rPolygonStrokeCandidate
)
986 // #i101491# method restructured to clearly use the DrawPolyLine
987 // calls starting from a deined line width
988 const attribute::LineAttribute
& rLineAttribute
= rPolygonStrokeCandidate
.getLineAttribute();
989 const double fLineWidth(rLineAttribute
.getWidth());
992 if(basegfx::fTools::more(fLineWidth
, 0.0))
994 const basegfx::B2DVector
aDiscreteUnit(maCurrentTransformation
* basegfx::B2DVector(fLineWidth
, 0.0));
995 const double fDiscreteLineWidth(aDiscreteUnit
.getLength());
996 const attribute::StrokeAttribute
& rStrokeAttribute
= rPolygonStrokeCandidate
.getStrokeAttribute();
997 const basegfx::BColor
aHairlineColor(maBColorModifierStack
.getModifiedColor(rLineAttribute
.getColor()));
998 basegfx::B2DPolyPolygon aHairlinePolyPolygon
;
1000 mpOutputDevice
->SetLineColor(Color(aHairlineColor
));
1001 mpOutputDevice
->SetFillColor();
1003 if(0.0 == rStrokeAttribute
.getFullDotDashLen())
1005 // no line dashing, just copy
1006 aHairlinePolyPolygon
.append(rPolygonStrokeCandidate
.getB2DPolygon());
1010 // else apply LineStyle
1011 basegfx::tools::applyLineDashing(rPolygonStrokeCandidate
.getB2DPolygon(),
1012 rStrokeAttribute
.getDotDashArray(),
1013 &aHairlinePolyPolygon
, 0, rStrokeAttribute
.getFullDotDashLen());
1016 const sal_uInt32
nCount(aHairlinePolyPolygon
.count());
1020 const bool bAntiAliased(getOptionsDrawinglayer().IsAntiAliasing());
1021 aHairlinePolyPolygon
.transform(maCurrentTransformation
);
1023 for(sal_uInt32
a(0); a
< nCount
; a
++)
1025 basegfx::B2DPolygon
aCandidate(aHairlinePolyPolygon
.getB2DPolygon(a
));
1029 if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth
, 1.0))
1031 // line in range ]0.0 .. 1.0[
1032 // paint as simple hairline
1033 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1036 else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth
, 2.0))
1038 // line in range [1.0 .. 2.0[
1039 // paint as 2x2 with dynamic line distance
1040 basegfx::B2DHomMatrix aMat
;
1041 const double fDistance(fDiscreteLineWidth
- 1.0);
1042 const double fHalfDistance(fDistance
* 0.5);
1044 aMat
.set(0, 2, -fHalfDistance
);
1045 aMat
.set(1, 2, -fHalfDistance
);
1046 aCandidate
.transform(aMat
);
1047 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1049 aMat
.set(0, 2, fDistance
);
1050 aMat
.set(1, 2, 0.0);
1051 aCandidate
.transform(aMat
);
1052 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1054 aMat
.set(0, 2, 0.0);
1055 aMat
.set(1, 2, fDistance
);
1056 aCandidate
.transform(aMat
);
1057 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1059 aMat
.set(0, 2, -fDistance
);
1060 aMat
.set(1, 2, 0.0);
1061 aCandidate
.transform(aMat
);
1062 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1065 else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth
, 3.0))
1067 // line in range [2.0 .. 3.0]
1068 // paint as cross in a 3x3 with dynamic line distance
1069 basegfx::B2DHomMatrix aMat
;
1070 const double fDistance((fDiscreteLineWidth
- 1.0) * 0.5);
1072 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1074 aMat
.set(0, 2, -fDistance
);
1075 aMat
.set(1, 2, 0.0);
1076 aCandidate
.transform(aMat
);
1077 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1079 aMat
.set(0, 2, fDistance
);
1080 aMat
.set(1, 2, -fDistance
);
1081 aCandidate
.transform(aMat
);
1082 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1084 aMat
.set(0, 2, fDistance
);
1085 aMat
.set(1, 2, fDistance
);
1086 aCandidate
.transform(aMat
);
1087 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1089 aMat
.set(0, 2, -fDistance
);
1090 aMat
.set(1, 2, fDistance
);
1091 aCandidate
.transform(aMat
);
1092 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1097 // #i101491# line width above 3.0
1102 if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth
, 1.5))
1104 // line width below 1.5, draw the basic hairline polygon
1105 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1108 else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth
, 2.5))
1110 // line width is in range ]1.5 .. 2.5], use four hairlines
1111 // drawn in a square
1112 basegfx::B2DHomMatrix aMat
;
1113 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1115 aMat
.set(0, 2, 1.0);
1116 aMat
.set(1, 2, 0.0);
1117 aCandidate
.transform(aMat
);
1119 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1121 aMat
.set(0, 2, 0.0);
1122 aMat
.set(1, 2, 1.0);
1123 aCandidate
.transform(aMat
);
1125 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1127 aMat
.set(0, 2, -1.0);
1128 aMat
.set(1, 2, 0.0);
1129 aCandidate
.transform(aMat
);
1131 mpOutputDevice
->DrawPolyLine(aCandidate
, 0.0);
1136 // #i101491# line width is above 2.5
1140 if(!bDone
&& rPolygonStrokeCandidate
.getB2DPolygon().count() > 1000)
1142 // #i101491# If the polygon complexity uses more than a given amount, do
1143 // use OuputDevice::DrawPolyLine directly; this will avoid buffering all
1144 // decompositions in primtives (memory) and fallback to old line painting
1145 // for very complex polygons, too
1146 mpOutputDevice
->DrawPolyLine(aCandidate
, fDiscreteLineWidth
, rLineAttribute
.getLineJoin());
1155 // remeber that we enter a PolygonStrokePrimitive2D decomposition,
1156 // used for AA thick line drawing
1157 mnPolygonStrokePrimitive2D
++;
1159 // line width is big enough for standard filled polygon visualisation or zero
1160 process(rPolygonStrokeCandidate
.get2DDecomposition(getViewInformation2D()));
1162 // leave PolygonStrokePrimitive2D
1163 mnPolygonStrokePrimitive2D
--;
1167 void VclProcessor2D::adaptLineToFillDrawMode() const
1169 const sal_uInt32
nOriginalDrawMode(mpOutputDevice
->GetDrawMode());
1171 if(nOriginalDrawMode
& (DRAWMODE_BLACKLINE
|DRAWMODE_GRAYLINE
|DRAWMODE_GHOSTEDLINE
|DRAWMODE_WHITELINE
|DRAWMODE_SETTINGSLINE
))
1173 sal_uInt32
nAdaptedDrawMode(nOriginalDrawMode
);
1175 if(nOriginalDrawMode
& DRAWMODE_BLACKLINE
)
1177 nAdaptedDrawMode
|= DRAWMODE_BLACKFILL
;
1181 nAdaptedDrawMode
&= ~DRAWMODE_BLACKFILL
;
1184 if(nOriginalDrawMode
& DRAWMODE_GRAYLINE
)
1186 nAdaptedDrawMode
|= DRAWMODE_GRAYFILL
;
1190 nAdaptedDrawMode
&= ~DRAWMODE_GRAYFILL
;
1193 if(nOriginalDrawMode
& DRAWMODE_GHOSTEDLINE
)
1195 nAdaptedDrawMode
|= DRAWMODE_GHOSTEDFILL
;
1199 nAdaptedDrawMode
&= ~DRAWMODE_GHOSTEDFILL
;
1202 if(nOriginalDrawMode
& DRAWMODE_WHITELINE
)
1204 nAdaptedDrawMode
|= DRAWMODE_WHITEFILL
;
1208 nAdaptedDrawMode
&= ~DRAWMODE_WHITEFILL
;
1211 if(nOriginalDrawMode
& DRAWMODE_SETTINGSLINE
)
1213 nAdaptedDrawMode
|= DRAWMODE_SETTINGSFILL
;
1217 nAdaptedDrawMode
&= ~DRAWMODE_SETTINGSFILL
;
1220 mpOutputDevice
->SetDrawMode(nAdaptedDrawMode
);
1224 void VclProcessor2D::adaptTextToFillDrawMode() const
1226 const sal_uInt32
nOriginalDrawMode(mpOutputDevice
->GetDrawMode());
1227 if(nOriginalDrawMode
& (DRAWMODE_BLACKTEXT
|DRAWMODE_GRAYTEXT
|DRAWMODE_GHOSTEDTEXT
|DRAWMODE_WHITETEXT
|DRAWMODE_SETTINGSTEXT
))
1229 sal_uInt32
nAdaptedDrawMode(nOriginalDrawMode
);
1231 if(nOriginalDrawMode
& DRAWMODE_BLACKTEXT
)
1233 nAdaptedDrawMode
|= DRAWMODE_BLACKFILL
;
1237 nAdaptedDrawMode
&= ~DRAWMODE_BLACKFILL
;
1240 if(nOriginalDrawMode
& DRAWMODE_GRAYTEXT
)
1242 nAdaptedDrawMode
|= DRAWMODE_GRAYFILL
;
1246 nAdaptedDrawMode
&= ~DRAWMODE_GRAYFILL
;
1249 if(nOriginalDrawMode
& DRAWMODE_GHOSTEDTEXT
)
1251 nAdaptedDrawMode
|= DRAWMODE_GHOSTEDFILL
;
1255 nAdaptedDrawMode
&= ~DRAWMODE_GHOSTEDFILL
;
1258 if(nOriginalDrawMode
& DRAWMODE_WHITETEXT
)
1260 nAdaptedDrawMode
|= DRAWMODE_WHITEFILL
;
1264 nAdaptedDrawMode
&= ~DRAWMODE_WHITEFILL
;
1267 if(nOriginalDrawMode
& DRAWMODE_SETTINGSTEXT
)
1269 nAdaptedDrawMode
|= DRAWMODE_SETTINGSFILL
;
1273 nAdaptedDrawMode
&= ~DRAWMODE_SETTINGSFILL
;
1276 mpOutputDevice
->SetDrawMode(nAdaptedDrawMode
);
1280 //////////////////////////////////////////////////////////////////////////////
1283 VclProcessor2D::VclProcessor2D(
1284 const geometry::ViewInformation2D
& rViewInformation
,
1285 OutputDevice
& rOutDev
)
1286 : BaseProcessor2D(rViewInformation
),
1287 mpOutputDevice(&rOutDev
),
1288 maBColorModifierStack(),
1289 maCurrentTransformation(),
1290 maDrawinglayerOpt(),
1291 mnPolygonStrokePrimitive2D(0)
1293 // set digit language, derived from SvtCTLOptions to have the correct
1294 // number display for arabic/hindi numerals
1295 const SvtCTLOptions aSvtCTLOptions
;
1296 LanguageType
eLang(LANGUAGE_SYSTEM
);
1298 if(SvtCTLOptions::NUMERALS_HINDI
== aSvtCTLOptions
.GetCTLTextNumerals())
1300 eLang
= LANGUAGE_ARABIC_SAUDI_ARABIA
;
1302 else if(SvtCTLOptions::NUMERALS_ARABIC
== aSvtCTLOptions
.GetCTLTextNumerals())
1304 eLang
= LANGUAGE_ENGLISH
;
1308 eLang
= (LanguageType
)Application::GetSettings().GetLanguage();
1311 rOutDev
.SetDigitLanguage(eLang
);
1314 VclProcessor2D::~VclProcessor2D()
1317 } // end of namespace processor2d
1318 } // end of namespace drawinglayer
1320 //////////////////////////////////////////////////////////////////////////////