merge the formfield patch from ooo-build
[ooovba.git] / drawinglayer / source / processor2d / vclprocessor2d.cxx
blob4f803e9366303af67c24cf4f55988415c54bf64a
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,
28 * MA 02111-1307 USA
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 //////////////////////////////////////////////////////////////////////////////
68 // control support
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
89 namespace processor2d
91 //////////////////////////////////////////////////////////////////////////////
92 // UNO class usages
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)
104 switch(eLineStyle)
106 default:
107 DBG_WARNING1( "DrawingLayer: Unknown text line style attribute (%d)!", eLineStyle );
108 // fall through
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 //////////////////////////////////////////////////////////////////////////////
131 // rendering support
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
136 // for VCL)
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);
154 fRotate += F_PI;
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(),
162 aFontScaling.getX(),
163 aFontScaling.getY(),
164 fRotate,
165 rTextCandidate.getLocale()));
167 // handle additional font attributes
168 const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP =
169 dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>( &rTextCandidate );
171 if( pTCPP != NULL )
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() )
204 default:
205 DBG_WARNING1( "DrawingLayer: Unknown strikeout attribute (%d)!", pTCPP->getFontStrikeout() );
206 // fall through
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() )
222 default:
223 DBG_WARNING1( "DrawingLayer: Unknown EmphasisMark style (%d)!", pTCPP->getFontEmphasisMark() );
224 // fall through
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;
238 else
239 eFontEmphasisMark |= EMPHASISMARK_POS_BELOW;
240 aFont.SetEmphasisMark( eFontEmphasisMark );
243 // set Relief attribute
244 FontRelief eFontRelief = RELIEF_NONE;
245 switch( pTCPP->getFontRelief() )
247 default:
248 DBG_WARNING1( "DrawingLayer: Unknown Relief style (%d)!", pTCPP->getFontRelief() );
249 // fall through
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(
298 aStartPoint,
299 rTextCandidate.getText(),
300 &(aTransformedDXArray[0]),
301 rTextCandidate.getTextPosition(),
302 rTextCandidate.getTextLength());
304 else
306 mpOutputDevice->DrawText(
307 aStartPoint,
308 rTextCandidate.getText(),
309 rTextCandidate.getTextPosition(),
310 rTextCandidate.getTextLength());
313 if(rTextCandidate.getFontAttributes().getRTL())
315 mpOutputDevice->SetLayoutMode(nOldLayoutMode);
318 bPrimitiveAccepted = true;
322 if(!bPrimitiveAccepted)
324 // let break down
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())
341 // #i98289#
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);
375 bPainted = true;
379 if(!bPainted)
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);
395 else
397 RenderBitmapPrimitive2D_GraphicManager(*mpOutputDevice, aBitmapEx, aLocalTransform);
400 else
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);
449 bPainted = true;
453 if(!bPainted)
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);
509 // prepare OutDev
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);
528 // restore OutDev
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);
559 else
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);
603 if(bFilled)
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);
612 if(bLine)
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);
642 fRotate += F_PI;
645 // get BoundRect
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));
670 else
672 aMetaFile = rMetaCandidate.getMetaFile();
675 // rotation
676 if(!basegfx::fTools::equalZero(fRotate))
678 // #i103530#
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));
683 while(nRotation < 0)
684 nRotation += 3600;
686 while(nRotation >= 3600)
687 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());
712 // paint it
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());
725 if(aMask.count())
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();
737 // paint to it
738 process(rMaskCandidate.getChildren());
740 // back to old OutDev
741 mpOutputDevice = pLastOutputDevice;
743 // draw mask
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();
755 else
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)
791 // use decomposition
792 process(rTransCandidate.get2DDecomposition(getViewInformation2D()));
794 else
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());
846 // set to mask
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();
868 // transform group.
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);
887 // proccess content
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);
918 // marker
919 void VclProcessor2D::RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D& rMarkArrayCandidate)
921 static bool bCheckCompleteMarkerDecompose(false);
922 if(bCheckCompleteMarkerDecompose)
924 process(rMarkArrayCandidate.get2DDecomposition(getViewInformation2D()));
925 return;
928 // get data
929 const std::vector< basegfx::B2DPoint >& rPositions = rMarkArrayCandidate.getPositions();
930 const sal_uInt32 nCount(rPositions.size());
932 if(nCount && !rMarkArrayCandidate.getMarker().IsEmpty())
934 // get pixel size
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);
968 // point
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());
990 bool bDone(false);
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());
1008 else
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());
1018 if(nCount)
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));
1027 if(bAntiAliased)
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);
1034 bDone = true;
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);
1063 bDone = true;
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);
1093 bDone = true;
1095 else
1097 // #i101491# line width above 3.0
1100 else
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);
1106 bDone = true;
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);
1132 bDone = true;
1134 else
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());
1147 bDone = true;
1153 if(!bDone)
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;
1179 else
1181 nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL;
1184 if(nOriginalDrawMode & DRAWMODE_GRAYLINE)
1186 nAdaptedDrawMode |= DRAWMODE_GRAYFILL;
1188 else
1190 nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL;
1193 if(nOriginalDrawMode & DRAWMODE_GHOSTEDLINE)
1195 nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL;
1197 else
1199 nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL;
1202 if(nOriginalDrawMode & DRAWMODE_WHITELINE)
1204 nAdaptedDrawMode |= DRAWMODE_WHITEFILL;
1206 else
1208 nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL;
1211 if(nOriginalDrawMode & DRAWMODE_SETTINGSLINE)
1213 nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL;
1215 else
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;
1235 else
1237 nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL;
1240 if(nOriginalDrawMode & DRAWMODE_GRAYTEXT)
1242 nAdaptedDrawMode |= DRAWMODE_GRAYFILL;
1244 else
1246 nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL;
1249 if(nOriginalDrawMode & DRAWMODE_GHOSTEDTEXT)
1251 nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL;
1253 else
1255 nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL;
1258 if(nOriginalDrawMode & DRAWMODE_WHITETEXT)
1260 nAdaptedDrawMode |= DRAWMODE_WHITEFILL;
1262 else
1264 nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL;
1267 if(nOriginalDrawMode & DRAWMODE_SETTINGSTEXT)
1269 nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL;
1271 else
1273 nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL;
1276 mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
1280 //////////////////////////////////////////////////////////////////////////////
1281 // process support
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;
1306 else
1308 eLang = (LanguageType)Application::GetSettings().GetLanguage();
1311 rOutDev.SetDigitLanguage(eLang);
1314 VclProcessor2D::~VclProcessor2D()
1317 } // end of namespace processor2d
1318 } // end of namespace drawinglayer
1320 //////////////////////////////////////////////////////////////////////////////
1321 // eof