1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_drawinglayer.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include <drawinglayer/processor2d/vclprocessor2d.hxx>
28*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/textprimitive2d.hxx>
29*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
30*b1cdbd2cSJim Jagielski #include <tools/debug.hxx>
31*b1cdbd2cSJim Jagielski #include <vcl/outdev.hxx>
32*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
33*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
34*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygontools.hxx>
35*b1cdbd2cSJim Jagielski #include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
36*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
37*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
38*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
39*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
40*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolypolygontools.hxx>
41*b1cdbd2cSJim Jagielski #include <vclhelperbufferdevice.hxx>
42*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
43*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
44*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/transparenceprimitive2d.hxx>
45*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
46*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
47*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/pointarrayprimitive2d.hxx>
48*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
49*b1cdbd2cSJim Jagielski #include <svl/ctloptions.hxx>
50*b1cdbd2cSJim Jagielski #include <vcl/svapp.hxx>
51*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/pagepreviewprimitive2d.hxx>
52*b1cdbd2cSJim Jagielski #include <tools/diagnose_ex.h>
53*b1cdbd2cSJim Jagielski #include <vcl/metric.hxx>
54*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/textenumsprimitive2d.hxx>
55*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/epsprimitive2d.hxx>
56*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
57*b1cdbd2cSJim Jagielski #include <basegfx/color/bcolor.hxx>
58*b1cdbd2cSJim Jagielski #include <basegfx/matrix/b2dhommatrixtools.hxx>
59*b1cdbd2cSJim Jagielski #include <vcl/graph.hxx>
60*b1cdbd2cSJim Jagielski 
61*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
62*b1cdbd2cSJim Jagielski // control support
63*b1cdbd2cSJim Jagielski 
64*b1cdbd2cSJim Jagielski #include <com/sun/star/awt/XWindow2.hpp>
65*b1cdbd2cSJim Jagielski #include <com/sun/star/awt/PosSize.hpp>
66*b1cdbd2cSJim Jagielski #include <com/sun/star/awt/XView.hpp>
67*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
68*b1cdbd2cSJim Jagielski #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
69*b1cdbd2cSJim Jagielski 
70*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
71*b1cdbd2cSJim Jagielski // for test, can be removed again
72*b1cdbd2cSJim Jagielski 
73*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dpolygonclipper.hxx>
74*b1cdbd2cSJim Jagielski #include <basegfx/polygon/b2dtrapezoid.hxx>
75*b1cdbd2cSJim Jagielski 
76*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
77*b1cdbd2cSJim Jagielski 
78*b1cdbd2cSJim Jagielski using namespace com::sun::star;
79*b1cdbd2cSJim Jagielski 
80*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
81*b1cdbd2cSJim Jagielski 
82*b1cdbd2cSJim Jagielski namespace
83*b1cdbd2cSJim Jagielski {
calculateStepsForSvgGradient(const basegfx::BColor & rColorA,const basegfx::BColor & rColorB,double fDelta,double fDiscreteUnit)84*b1cdbd2cSJim Jagielski     sal_uInt32 calculateStepsForSvgGradient(const basegfx::BColor& rColorA, const basegfx::BColor& rColorB, double fDelta, double fDiscreteUnit)
85*b1cdbd2cSJim Jagielski     {
86*b1cdbd2cSJim Jagielski         // use color distance, assume to do every color step
87*b1cdbd2cSJim Jagielski         sal_uInt32 nSteps(basegfx::fround(rColorA.getDistance(rColorB) * 255.0));
88*b1cdbd2cSJim Jagielski 
89*b1cdbd2cSJim Jagielski         if(nSteps)
90*b1cdbd2cSJim Jagielski         {
91*b1cdbd2cSJim Jagielski             // calc discrete length to change color each disctete unit (pixel)
92*b1cdbd2cSJim Jagielski             const sal_uInt32 nDistSteps(basegfx::fround(fDelta / fDiscreteUnit));
93*b1cdbd2cSJim Jagielski 
94*b1cdbd2cSJim Jagielski             nSteps = std::min(nSteps, nDistSteps);
95*b1cdbd2cSJim Jagielski         }
96*b1cdbd2cSJim Jagielski 
97*b1cdbd2cSJim Jagielski         // reduce quality to 3 discrete units or every 3rd color step for rendering
98*b1cdbd2cSJim Jagielski         nSteps /= 2;
99*b1cdbd2cSJim Jagielski 
100*b1cdbd2cSJim Jagielski         // roughly cut when too big or too small (not full quality, reduce complexity)
101*b1cdbd2cSJim Jagielski         nSteps = std::min(nSteps, sal_uInt32(255));
102*b1cdbd2cSJim Jagielski         nSteps = std::max(nSteps, sal_uInt32(1));
103*b1cdbd2cSJim Jagielski 
104*b1cdbd2cSJim Jagielski         return nSteps;
105*b1cdbd2cSJim Jagielski     }
106*b1cdbd2cSJim Jagielski } // end of anonymous namespace
107*b1cdbd2cSJim Jagielski 
108*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
109*b1cdbd2cSJim Jagielski 
110*b1cdbd2cSJim Jagielski namespace drawinglayer
111*b1cdbd2cSJim Jagielski {
112*b1cdbd2cSJim Jagielski 	namespace processor2d
113*b1cdbd2cSJim Jagielski 	{
114*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////////////
115*b1cdbd2cSJim Jagielski 		// UNO class usages
116*b1cdbd2cSJim Jagielski 		using ::com::sun::star::uno::Reference;
117*b1cdbd2cSJim Jagielski 		using ::com::sun::star::uno::UNO_QUERY;
118*b1cdbd2cSJim Jagielski 	    using ::com::sun::star::uno::UNO_QUERY_THROW;
119*b1cdbd2cSJim Jagielski         using ::com::sun::star::uno::Exception;
120*b1cdbd2cSJim Jagielski 		using ::com::sun::star::awt::XView;
121*b1cdbd2cSJim Jagielski 		using ::com::sun::star::awt::XGraphics;
122*b1cdbd2cSJim Jagielski 	    using ::com::sun::star::awt::XWindow;
123*b1cdbd2cSJim Jagielski 	    using ::com::sun::star::awt::PosSize::POSSIZE;
124*b1cdbd2cSJim Jagielski 
125*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////////////
126*b1cdbd2cSJim Jagielski 		// rendering support
127*b1cdbd2cSJim Jagielski 
128*b1cdbd2cSJim Jagielski 		// directdraw of text simple portion or decorated portion primitive. When decorated, all the extra
129*b1cdbd2cSJim Jagielski 		// information is translated to VCL parameters and set at the font.
130*b1cdbd2cSJim Jagielski 		// Acceptance is restricted to no shearing and positive scaling in X and Y (no font mirroring
131*b1cdbd2cSJim Jagielski 		// for VCL)
RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D & rTextCandidate)132*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderTextSimpleOrDecoratedPortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
133*b1cdbd2cSJim Jagielski 		{
134*b1cdbd2cSJim Jagielski             // decompose matrix to have position and size of text
135*b1cdbd2cSJim Jagielski 			basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rTextCandidate.getTextTransform());
136*b1cdbd2cSJim Jagielski 			basegfx::B2DVector aFontScaling, aTranslate;
137*b1cdbd2cSJim Jagielski 			double fRotate, fShearX;
138*b1cdbd2cSJim Jagielski 			aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX);
139*b1cdbd2cSJim Jagielski 			bool bPrimitiveAccepted(false);
140*b1cdbd2cSJim Jagielski 
141*b1cdbd2cSJim Jagielski 			if(basegfx::fTools::equalZero(fShearX))
142*b1cdbd2cSJim Jagielski 			{
143*b1cdbd2cSJim Jagielski 				if(basegfx::fTools::less(aFontScaling.getX(), 0.0) && basegfx::fTools::less(aFontScaling.getY(), 0.0))
144*b1cdbd2cSJim Jagielski 				{
145*b1cdbd2cSJim Jagielski 					// handle special case: If scale is negative in (x,y) (3rd quadrant), it can
146*b1cdbd2cSJim Jagielski 					// be expressed as rotation by PI. Use this since the Font rendering will not
147*b1cdbd2cSJim Jagielski                     // apply the negative scales in any form
148*b1cdbd2cSJim Jagielski 					aFontScaling = basegfx::absolute(aFontScaling);
149*b1cdbd2cSJim Jagielski 					fRotate += F_PI;
150*b1cdbd2cSJim Jagielski 				}
151*b1cdbd2cSJim Jagielski 
152*b1cdbd2cSJim Jagielski 				if(basegfx::fTools::more(aFontScaling.getX(), 0.0) && basegfx::fTools::more(aFontScaling.getY(), 0.0))
153*b1cdbd2cSJim Jagielski 				{
154*b1cdbd2cSJim Jagielski                     // Get the VCL font (use FontHeight as FontWidth)
155*b1cdbd2cSJim Jagielski                     Font aFont(primitive2d::getVclFontFromFontAttribute(
156*b1cdbd2cSJim Jagielski                         rTextCandidate.getFontAttribute(),
157*b1cdbd2cSJim Jagielski                         aFontScaling.getX(),
158*b1cdbd2cSJim Jagielski                         aFontScaling.getY(),
159*b1cdbd2cSJim Jagielski                         fRotate,
160*b1cdbd2cSJim Jagielski                         rTextCandidate.getLocale()));
161*b1cdbd2cSJim Jagielski 
162*b1cdbd2cSJim Jagielski 					// handle additional font attributes
163*b1cdbd2cSJim Jagielski 					const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP =
164*b1cdbd2cSJim Jagielski 						dynamic_cast<const primitive2d::TextDecoratedPortionPrimitive2D*>( &rTextCandidate );
165*b1cdbd2cSJim Jagielski 
166*b1cdbd2cSJim Jagielski 					if( pTCPP != NULL )
167*b1cdbd2cSJim Jagielski 					{
168*b1cdbd2cSJim Jagielski 
169*b1cdbd2cSJim Jagielski                         // set the color of text decorations
170*b1cdbd2cSJim Jagielski                         const basegfx::BColor aTextlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getTextlineColor());
171*b1cdbd2cSJim Jagielski                         mpOutputDevice->SetTextLineColor( Color(aTextlineColor) );
172*b1cdbd2cSJim Jagielski 
173*b1cdbd2cSJim Jagielski                         // set Overline attribute
174*b1cdbd2cSJim Jagielski                         const FontUnderline eFontOverline(primitive2d::mapTextLineToFontUnderline( pTCPP->getFontOverline() ));
175*b1cdbd2cSJim Jagielski                         if( eFontOverline != UNDERLINE_NONE )
176*b1cdbd2cSJim Jagielski                         {
177*b1cdbd2cSJim Jagielski                             aFont.SetOverline( eFontOverline );
178*b1cdbd2cSJim Jagielski                             const basegfx::BColor aOverlineColor = maBColorModifierStack.getModifiedColor(pTCPP->getOverlineColor());
179*b1cdbd2cSJim Jagielski                             mpOutputDevice->SetOverlineColor( Color(aOverlineColor) );
180*b1cdbd2cSJim Jagielski                             if( pTCPP->getWordLineMode() )
181*b1cdbd2cSJim Jagielski                                 aFont.SetWordLineMode( true );
182*b1cdbd2cSJim Jagielski                         }
183*b1cdbd2cSJim Jagielski 
184*b1cdbd2cSJim Jagielski                         // set Underline attribute
185*b1cdbd2cSJim Jagielski                         const FontUnderline eFontUnderline(primitive2d::mapTextLineToFontUnderline( pTCPP->getFontUnderline() ));
186*b1cdbd2cSJim Jagielski                         if( eFontUnderline != UNDERLINE_NONE )
187*b1cdbd2cSJim Jagielski 						{
188*b1cdbd2cSJim Jagielski 							aFont.SetUnderline( eFontUnderline );
189*b1cdbd2cSJim Jagielski 							if( pTCPP->getWordLineMode() )
190*b1cdbd2cSJim Jagielski 								aFont.SetWordLineMode( true );
191*b1cdbd2cSJim Jagielski //TODO: ???					if( pTCPP->getUnderlineAbove() )
192*b1cdbd2cSJim Jagielski //								aFont.SetUnderlineAbove( true );
193*b1cdbd2cSJim Jagielski 						}
194*b1cdbd2cSJim Jagielski 
195*b1cdbd2cSJim Jagielski 						// set Strikeout attribute
196*b1cdbd2cSJim Jagielski 						const FontStrikeout eFontStrikeout(primitive2d::mapTextStrikeoutToFontStrikeout(pTCPP->getTextStrikeout()));
197*b1cdbd2cSJim Jagielski 
198*b1cdbd2cSJim Jagielski 						if( eFontStrikeout != STRIKEOUT_NONE )
199*b1cdbd2cSJim Jagielski 							aFont.SetStrikeout( eFontStrikeout );
200*b1cdbd2cSJim Jagielski 
201*b1cdbd2cSJim Jagielski 						// set EmphasisMark attribute
202*b1cdbd2cSJim Jagielski 						FontEmphasisMark eFontEmphasisMark = EMPHASISMARK_NONE;
203*b1cdbd2cSJim Jagielski 						switch( pTCPP->getTextEmphasisMark() )
204*b1cdbd2cSJim Jagielski 						{
205*b1cdbd2cSJim Jagielski 							default:
206*b1cdbd2cSJim Jagielski 								DBG_WARNING1( "DrawingLayer: Unknown EmphasisMark style (%d)!", pTCPP->getTextEmphasisMark() );
207*b1cdbd2cSJim Jagielski 								// fall through
208*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_EMPHASISMARK_NONE:	eFontEmphasisMark = EMPHASISMARK_NONE; break;
209*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_EMPHASISMARK_DOT:	eFontEmphasisMark = EMPHASISMARK_DOT; break;
210*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_EMPHASISMARK_CIRCLE:	eFontEmphasisMark = EMPHASISMARK_CIRCLE; break;
211*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_EMPHASISMARK_DISC:	eFontEmphasisMark = EMPHASISMARK_DISC; break;
212*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_EMPHASISMARK_ACCENT:	eFontEmphasisMark = EMPHASISMARK_ACCENT; break;
213*b1cdbd2cSJim Jagielski 						}
214*b1cdbd2cSJim Jagielski 
215*b1cdbd2cSJim Jagielski 						if( eFontEmphasisMark != EMPHASISMARK_NONE )
216*b1cdbd2cSJim Jagielski 						{
217*b1cdbd2cSJim Jagielski 							DBG_ASSERT( (pTCPP->getEmphasisMarkAbove() != pTCPP->getEmphasisMarkBelow()),
218*b1cdbd2cSJim Jagielski 								"DrawingLayer: Bad EmphasisMark position!" );
219*b1cdbd2cSJim Jagielski 							if( pTCPP->getEmphasisMarkAbove() )
220*b1cdbd2cSJim Jagielski 								eFontEmphasisMark |= EMPHASISMARK_POS_ABOVE;
221*b1cdbd2cSJim Jagielski 							else
222*b1cdbd2cSJim Jagielski 								eFontEmphasisMark |= EMPHASISMARK_POS_BELOW;
223*b1cdbd2cSJim Jagielski 							aFont.SetEmphasisMark( eFontEmphasisMark );
224*b1cdbd2cSJim Jagielski 						}
225*b1cdbd2cSJim Jagielski 
226*b1cdbd2cSJim Jagielski 						// set Relief attribute
227*b1cdbd2cSJim Jagielski 						FontRelief eFontRelief = RELIEF_NONE;
228*b1cdbd2cSJim Jagielski 						switch( pTCPP->getTextRelief() )
229*b1cdbd2cSJim Jagielski 						{
230*b1cdbd2cSJim Jagielski 							default:
231*b1cdbd2cSJim Jagielski 								DBG_WARNING1( "DrawingLayer: Unknown Relief style (%d)!", pTCPP->getTextRelief() );
232*b1cdbd2cSJim Jagielski 								// fall through
233*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_RELIEF_NONE:		eFontRelief = RELIEF_NONE; break;
234*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_RELIEF_EMBOSSED:	eFontRelief = RELIEF_EMBOSSED; break;
235*b1cdbd2cSJim Jagielski 							case primitive2d::TEXT_RELIEF_ENGRAVED:	eFontRelief = RELIEF_ENGRAVED; break;
236*b1cdbd2cSJim Jagielski 						}
237*b1cdbd2cSJim Jagielski 
238*b1cdbd2cSJim Jagielski 						if( eFontRelief != RELIEF_NONE )
239*b1cdbd2cSJim Jagielski 							aFont.SetRelief( eFontRelief );
240*b1cdbd2cSJim Jagielski 
241*b1cdbd2cSJim Jagielski 						// set Shadow attribute
242*b1cdbd2cSJim Jagielski 						if( pTCPP->getShadow() )
243*b1cdbd2cSJim Jagielski 							aFont.SetShadow( true );
244*b1cdbd2cSJim Jagielski 					}
245*b1cdbd2cSJim Jagielski 
246*b1cdbd2cSJim Jagielski 					// create transformed integer DXArray in view coordinate system
247*b1cdbd2cSJim Jagielski 					::std::vector< sal_Int32 > aTransformedDXArray;
248*b1cdbd2cSJim Jagielski 
249*b1cdbd2cSJim Jagielski 					if(rTextCandidate.getDXArray().size())
250*b1cdbd2cSJim Jagielski 					{
251*b1cdbd2cSJim Jagielski 						aTransformedDXArray.reserve(rTextCandidate.getDXArray().size());
252*b1cdbd2cSJim Jagielski 						const basegfx::B2DVector aPixelVector(maCurrentTransformation * basegfx::B2DVector(1.0, 0.0));
253*b1cdbd2cSJim Jagielski 						const double fPixelVectorFactor(aPixelVector.getLength());
254*b1cdbd2cSJim Jagielski 
255*b1cdbd2cSJim Jagielski 						for(::std::vector< double >::const_iterator aStart(rTextCandidate.getDXArray().begin());
256*b1cdbd2cSJim Jagielski                             aStart != rTextCandidate.getDXArray().end(); aStart++)
257*b1cdbd2cSJim Jagielski 						{
258*b1cdbd2cSJim Jagielski 							aTransformedDXArray.push_back(basegfx::fround((*aStart) * fPixelVectorFactor));
259*b1cdbd2cSJim Jagielski 						}
260*b1cdbd2cSJim Jagielski 					}
261*b1cdbd2cSJim Jagielski 
262*b1cdbd2cSJim Jagielski 					// set parameters and paint text snippet
263*b1cdbd2cSJim Jagielski 					const basegfx::BColor aRGBFontColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
264*b1cdbd2cSJim Jagielski 					const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
265*b1cdbd2cSJim Jagielski 					const Point aStartPoint(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()));
266*b1cdbd2cSJim Jagielski                     const sal_uInt32 nOldLayoutMode(mpOutputDevice->GetLayoutMode());
267*b1cdbd2cSJim Jagielski 
268*b1cdbd2cSJim Jagielski                     if(rTextCandidate.getFontAttribute().getRTL())
269*b1cdbd2cSJim Jagielski                     {
270*b1cdbd2cSJim Jagielski                         sal_uInt32 nRTLLayoutMode(nOldLayoutMode & ~(TEXT_LAYOUT_COMPLEX_DISABLED|TEXT_LAYOUT_BIDI_STRONG));
271*b1cdbd2cSJim Jagielski                         nRTLLayoutMode |= TEXT_LAYOUT_BIDI_RTL|TEXT_LAYOUT_TEXTORIGIN_LEFT;
272*b1cdbd2cSJim Jagielski                         mpOutputDevice->SetLayoutMode(nRTLLayoutMode);
273*b1cdbd2cSJim Jagielski                     }
274*b1cdbd2cSJim Jagielski 
275*b1cdbd2cSJim Jagielski 					mpOutputDevice->SetFont(aFont);
276*b1cdbd2cSJim Jagielski 					mpOutputDevice->SetTextColor(Color(aRGBFontColor));
277*b1cdbd2cSJim Jagielski 
278*b1cdbd2cSJim Jagielski 					if(aTransformedDXArray.size())
279*b1cdbd2cSJim Jagielski 					{
280*b1cdbd2cSJim Jagielski 						mpOutputDevice->DrawTextArray(
281*b1cdbd2cSJim Jagielski 							aStartPoint,
282*b1cdbd2cSJim Jagielski 							rTextCandidate.getText(),
283*b1cdbd2cSJim Jagielski 							&(aTransformedDXArray[0]),
284*b1cdbd2cSJim Jagielski 							rTextCandidate.getTextPosition(),
285*b1cdbd2cSJim Jagielski 							rTextCandidate.getTextLength());
286*b1cdbd2cSJim Jagielski 					}
287*b1cdbd2cSJim Jagielski 					else
288*b1cdbd2cSJim Jagielski 					{
289*b1cdbd2cSJim Jagielski 						mpOutputDevice->DrawText(
290*b1cdbd2cSJim Jagielski 							aStartPoint,
291*b1cdbd2cSJim Jagielski 							rTextCandidate.getText(),
292*b1cdbd2cSJim Jagielski 							rTextCandidate.getTextPosition(),
293*b1cdbd2cSJim Jagielski 							rTextCandidate.getTextLength());
294*b1cdbd2cSJim Jagielski 					}
295*b1cdbd2cSJim Jagielski 
296*b1cdbd2cSJim Jagielski                     if(rTextCandidate.getFontAttribute().getRTL())
297*b1cdbd2cSJim Jagielski                     {
298*b1cdbd2cSJim Jagielski                         mpOutputDevice->SetLayoutMode(nOldLayoutMode);
299*b1cdbd2cSJim Jagielski                     }
300*b1cdbd2cSJim Jagielski 
301*b1cdbd2cSJim Jagielski 					bPrimitiveAccepted = true;
302*b1cdbd2cSJim Jagielski 				}
303*b1cdbd2cSJim Jagielski 			}
304*b1cdbd2cSJim Jagielski 
305*b1cdbd2cSJim Jagielski 			if(!bPrimitiveAccepted)
306*b1cdbd2cSJim Jagielski 			{
307*b1cdbd2cSJim Jagielski 				// let break down
308*b1cdbd2cSJim Jagielski 				process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
309*b1cdbd2cSJim Jagielski 			}
310*b1cdbd2cSJim Jagielski 		}
311*b1cdbd2cSJim Jagielski 
312*b1cdbd2cSJim Jagielski 		// direct draw of hairline
RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D & rPolygonCandidate,bool bPixelBased)313*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate, bool bPixelBased)
314*b1cdbd2cSJim Jagielski 		{
315*b1cdbd2cSJim Jagielski             const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
316*b1cdbd2cSJim Jagielski 			mpOutputDevice->SetLineColor(Color(aHairlineColor));
317*b1cdbd2cSJim Jagielski 			mpOutputDevice->SetFillColor();
318*b1cdbd2cSJim Jagielski 
319*b1cdbd2cSJim Jagielski 			basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
320*b1cdbd2cSJim Jagielski 			aLocalPolygon.transform(maCurrentTransformation);
321*b1cdbd2cSJim Jagielski 
322*b1cdbd2cSJim Jagielski             static bool bCheckTrapezoidDecomposition(false);
323*b1cdbd2cSJim Jagielski             static bool bShowOutlinesThere(false);
324*b1cdbd2cSJim Jagielski             if(bCheckTrapezoidDecomposition)
325*b1cdbd2cSJim Jagielski             {
326*b1cdbd2cSJim Jagielski                 // clip against discrete ViewPort
327*b1cdbd2cSJim Jagielski                 const basegfx::B2DRange& rDiscreteViewport = getViewInformation2D().getDiscreteViewport();
328*b1cdbd2cSJim Jagielski                 basegfx::B2DPolyPolygon aLocalPolyPolygon(basegfx::tools::clipPolygonOnRange(
329*b1cdbd2cSJim Jagielski                     aLocalPolygon, rDiscreteViewport, true, false));
330*b1cdbd2cSJim Jagielski 
331*b1cdbd2cSJim Jagielski                 if(aLocalPolyPolygon.count())
332*b1cdbd2cSJim Jagielski                 {
333*b1cdbd2cSJim Jagielski                     // subdivide
334*b1cdbd2cSJim Jagielski                     aLocalPolyPolygon = basegfx::tools::adaptiveSubdivideByDistance(
335*b1cdbd2cSJim Jagielski                         aLocalPolyPolygon, 0.5);
336*b1cdbd2cSJim Jagielski 
337*b1cdbd2cSJim Jagielski                     // trapezoidize
338*b1cdbd2cSJim Jagielski                     static double fLineWidth(2.0);
339*b1cdbd2cSJim Jagielski                     basegfx::B2DTrapezoidVector aB2DTrapezoidVector;
340*b1cdbd2cSJim Jagielski                     basegfx::tools::createLineTrapezoidFromB2DPolyPolygon(aB2DTrapezoidVector, aLocalPolyPolygon, fLineWidth);
341*b1cdbd2cSJim Jagielski 
342*b1cdbd2cSJim Jagielski                     const sal_uInt32 nCount(aB2DTrapezoidVector.size());
343*b1cdbd2cSJim Jagielski 
344*b1cdbd2cSJim Jagielski                     if(nCount)
345*b1cdbd2cSJim Jagielski                     {
346*b1cdbd2cSJim Jagielski                         basegfx::BColor aInvPolygonColor(aHairlineColor);
347*b1cdbd2cSJim Jagielski                         aInvPolygonColor.invert();
348*b1cdbd2cSJim Jagielski 
349*b1cdbd2cSJim Jagielski                         for(sal_uInt32 a(0); a < nCount; a++)
350*b1cdbd2cSJim Jagielski                         {
351*b1cdbd2cSJim Jagielski                             const basegfx::B2DPolygon aTempPolygon(aB2DTrapezoidVector[a].getB2DPolygon());
352*b1cdbd2cSJim Jagielski 
353*b1cdbd2cSJim Jagielski                             if(bShowOutlinesThere)
354*b1cdbd2cSJim Jagielski                             {
355*b1cdbd2cSJim Jagielski                                 mpOutputDevice->SetFillColor(Color(aHairlineColor));
356*b1cdbd2cSJim Jagielski 			                    mpOutputDevice->SetLineColor();
357*b1cdbd2cSJim Jagielski                             }
358*b1cdbd2cSJim Jagielski 
359*b1cdbd2cSJim Jagielski                             mpOutputDevice->DrawPolygon(aTempPolygon);
360*b1cdbd2cSJim Jagielski 
361*b1cdbd2cSJim Jagielski                             if(bShowOutlinesThere)
362*b1cdbd2cSJim Jagielski                             {
363*b1cdbd2cSJim Jagielski                                 mpOutputDevice->SetFillColor();
364*b1cdbd2cSJim Jagielski         		                mpOutputDevice->SetLineColor(Color(aInvPolygonColor));
365*b1cdbd2cSJim Jagielski     	    		            mpOutputDevice->DrawPolyLine(aTempPolygon, 0.0);
366*b1cdbd2cSJim Jagielski                             }
367*b1cdbd2cSJim Jagielski                         }
368*b1cdbd2cSJim Jagielski                     }
369*b1cdbd2cSJim Jagielski                 }
370*b1cdbd2cSJim Jagielski             }
371*b1cdbd2cSJim Jagielski             else
372*b1cdbd2cSJim Jagielski             {
373*b1cdbd2cSJim Jagielski 			    if(bPixelBased && getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete())
374*b1cdbd2cSJim Jagielski 			    {
375*b1cdbd2cSJim Jagielski 				    // #i98289#
376*b1cdbd2cSJim Jagielski 				    // when a Hairline is painted and AntiAliasing is on the option SnapHorVerLinesToDiscrete
377*b1cdbd2cSJim Jagielski 				    // allows to suppress AntiAliasing for pure horizontal or vertical lines. This is done since
378*b1cdbd2cSJim Jagielski 				    // not-AntiAliased such lines look more pleasing to the eye (e.g. 2D chart content). This
379*b1cdbd2cSJim Jagielski 				    // NEEDS to be done in discrete coordinates, so only useful for pixel based rendering.
380*b1cdbd2cSJim Jagielski 				    aLocalPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aLocalPolygon);
381*b1cdbd2cSJim Jagielski 			    }
382*b1cdbd2cSJim Jagielski 
383*b1cdbd2cSJim Jagielski 			    mpOutputDevice->DrawPolyLine(aLocalPolygon, 0.0);
384*b1cdbd2cSJim Jagielski             }
385*b1cdbd2cSJim Jagielski 		}
386*b1cdbd2cSJim Jagielski 
387*b1cdbd2cSJim Jagielski 		// direct draw of transformed BitmapEx primitive
RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D & rBitmapCandidate)388*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
389*b1cdbd2cSJim Jagielski 		{
390*b1cdbd2cSJim Jagielski             BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx());
391*b1cdbd2cSJim Jagielski             const basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rBitmapCandidate.getTransform());
392*b1cdbd2cSJim Jagielski 
393*b1cdbd2cSJim Jagielski 			if(maBColorModifierStack.count())
394*b1cdbd2cSJim Jagielski 			{
395*b1cdbd2cSJim Jagielski                 aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
396*b1cdbd2cSJim Jagielski 
397*b1cdbd2cSJim Jagielski 				if(aBitmapEx.IsEmpty())
398*b1cdbd2cSJim Jagielski 				{
399*b1cdbd2cSJim Jagielski 					// color gets completely replaced, get it
400*b1cdbd2cSJim Jagielski 					const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
401*b1cdbd2cSJim Jagielski 					basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
402*b1cdbd2cSJim Jagielski 					aPolygon.transform(aLocalTransform);
403*b1cdbd2cSJim Jagielski 
404*b1cdbd2cSJim Jagielski 					mpOutputDevice->SetFillColor(Color(aModifiedColor));
405*b1cdbd2cSJim Jagielski 					mpOutputDevice->SetLineColor();
406*b1cdbd2cSJim Jagielski 					mpOutputDevice->DrawPolygon(aPolygon);
407*b1cdbd2cSJim Jagielski 
408*b1cdbd2cSJim Jagielski 					return;
409*b1cdbd2cSJim Jagielski 				}
410*b1cdbd2cSJim Jagielski 			}
411*b1cdbd2cSJim Jagielski 
412*b1cdbd2cSJim Jagielski             // #122923# do no longer add Alpha channel here; the right place to do this is when really
413*b1cdbd2cSJim Jagielski             // the own transformer is used (see OutputDevice::DrawTransformedBitmapEx).
414*b1cdbd2cSJim Jagielski 
415*b1cdbd2cSJim Jagielski             // draw using OutputDevice'sDrawTransformedBitmapEx
416*b1cdbd2cSJim Jagielski             mpOutputDevice->DrawTransformedBitmapEx(aLocalTransform, aBitmapEx);
417*b1cdbd2cSJim Jagielski 		}
418*b1cdbd2cSJim Jagielski 
RenderFillGraphicPrimitive2D(const primitive2d::FillGraphicPrimitive2D & rFillBitmapCandidate)419*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderFillGraphicPrimitive2D(const primitive2d::FillGraphicPrimitive2D& rFillBitmapCandidate)
420*b1cdbd2cSJim Jagielski 		{
421*b1cdbd2cSJim Jagielski 			const attribute::FillGraphicAttribute& rFillGraphicAttribute(rFillBitmapCandidate.getFillGraphic());
422*b1cdbd2cSJim Jagielski 			bool bPrimitiveAccepted(false);
423*b1cdbd2cSJim Jagielski             static bool bTryTilingDirect = true;
424*b1cdbd2cSJim Jagielski 
425*b1cdbd2cSJim Jagielski             // #121194# when tiling is used and content is bitmap-based, do direct tiling in the
426*b1cdbd2cSJim Jagielski             // renderer on pixel base to ensure tight fitting. Do not do this when
427*b1cdbd2cSJim Jagielski             // the fill is rotated or sheared.
428*b1cdbd2cSJim Jagielski 
429*b1cdbd2cSJim Jagielski             // ovveride static bool (for debug) and tiling is active
430*b1cdbd2cSJim Jagielski 			if(bTryTilingDirect && rFillGraphicAttribute.getTiling())
431*b1cdbd2cSJim Jagielski 			{
432*b1cdbd2cSJim Jagielski                 // content is bitmap(ex)
433*b1cdbd2cSJim Jagielski                 //
434*b1cdbd2cSJim Jagielski                 // for SVG support, force decomposition when SVG is present. This will lead to use
435*b1cdbd2cSJim Jagielski                 // the primitive representation of the svg directly.
436*b1cdbd2cSJim Jagielski                 //
437*b1cdbd2cSJim Jagielski                 // when graphic is animated, force decomposition to use the correct graphic, else
438*b1cdbd2cSJim Jagielski                 // fill style will not be animated
439*b1cdbd2cSJim Jagielski                 if(GRAPHIC_BITMAP == rFillGraphicAttribute.getGraphic().GetType()
440*b1cdbd2cSJim Jagielski                     && !rFillGraphicAttribute.getGraphic().getSvgData().get()
441*b1cdbd2cSJim Jagielski                     && !rFillGraphicAttribute.getGraphic().IsAnimated())
442*b1cdbd2cSJim Jagielski                 {
443*b1cdbd2cSJim Jagielski 				    // decompose matrix to check for shear, rotate and mirroring
444*b1cdbd2cSJim Jagielski 				    basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rFillBitmapCandidate.getTransformation());
445*b1cdbd2cSJim Jagielski 				    basegfx::B2DVector aScale, aTranslate;
446*b1cdbd2cSJim Jagielski 				    double fRotate, fShearX;
447*b1cdbd2cSJim Jagielski 				    aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
448*b1cdbd2cSJim Jagielski 
449*b1cdbd2cSJim Jagielski                     // when nopt rotated/sheared
450*b1cdbd2cSJim Jagielski 				    if(basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX))
451*b1cdbd2cSJim Jagielski 				    {
452*b1cdbd2cSJim Jagielski 					    // no shear or rotate, draw direct in pixel coordinates
453*b1cdbd2cSJim Jagielski 					    bPrimitiveAccepted = true;
454*b1cdbd2cSJim Jagielski 
455*b1cdbd2cSJim Jagielski                         // transform object range to device coordinates (pixels). Use
456*b1cdbd2cSJim Jagielski                         // the device transformation for better accuracy
457*b1cdbd2cSJim Jagielski                         basegfx::B2DRange aObjectRange(aTranslate, aTranslate + aScale);
458*b1cdbd2cSJim Jagielski                         aObjectRange.transform(mpOutputDevice->GetViewTransformation());
459*b1cdbd2cSJim Jagielski 
460*b1cdbd2cSJim Jagielski                         // extract discrete size of object
461*b1cdbd2cSJim Jagielski                         const sal_Int32 nOWidth(basegfx::fround(aObjectRange.getWidth()));
462*b1cdbd2cSJim Jagielski                         const sal_Int32 nOHeight(basegfx::fround(aObjectRange.getHeight()));
463*b1cdbd2cSJim Jagielski 
464*b1cdbd2cSJim Jagielski                         // only do something when object has a size in discrete units
465*b1cdbd2cSJim Jagielski 						if(nOWidth > 0 && nOHeight > 0)
466*b1cdbd2cSJim Jagielski 						{
467*b1cdbd2cSJim Jagielski                             // transform graphic range to device coordinates (pixels). Use
468*b1cdbd2cSJim Jagielski                             // the device transformation for better accuracy
469*b1cdbd2cSJim Jagielski                             basegfx::B2DRange aGraphicRange(rFillGraphicAttribute.getGraphicRange());
470*b1cdbd2cSJim Jagielski                             aGraphicRange.transform(mpOutputDevice->GetViewTransformation() * aLocalTransform);
471*b1cdbd2cSJim Jagielski 
472*b1cdbd2cSJim Jagielski                             // extract discrete size of graphic
473*b1cdbd2cSJim Jagielski                             // caution: when getting to zero, nothing would be painted; thus, do not allow this
474*b1cdbd2cSJim Jagielski                             const sal_Int32 nBWidth(std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getWidth())));
475*b1cdbd2cSJim Jagielski                             const sal_Int32 nBHeight(std::max(sal_Int32(1), basegfx::fround(aGraphicRange.getHeight())));
476*b1cdbd2cSJim Jagielski 
477*b1cdbd2cSJim Jagielski                             // only do something when bitmap fill has a size in discrete units
478*b1cdbd2cSJim Jagielski 						    if(nBWidth > 0 && nBHeight > 0)
479*b1cdbd2cSJim Jagielski 						    {
480*b1cdbd2cSJim Jagielski 						        // nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it
481*b1cdbd2cSJim Jagielski 						        // in vcl many times, create a size-optimized version
482*b1cdbd2cSJim Jagielski 						        const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
483*b1cdbd2cSJim Jagielski                                 BitmapEx aBitmapEx(rFillGraphicAttribute.getGraphic().GetBitmapEx());
484*b1cdbd2cSJim Jagielski                                 static bool bEnablePreScaling(true);
485*b1cdbd2cSJim Jagielski                                 const bool bPreScaled(bEnablePreScaling && nBWidth * nBHeight < (250 * 250));
486*b1cdbd2cSJim Jagielski 
487*b1cdbd2cSJim Jagielski                                 // ... but only up to a maximum size, else it gets too expensive
488*b1cdbd2cSJim Jagielski                                 if(bPreScaled)
489*b1cdbd2cSJim Jagielski                                 {
490*b1cdbd2cSJim Jagielski                                     // if color depth is below 24bit, expand before scaling for better quality.
491*b1cdbd2cSJim Jagielski                                     // This is even needed for low colors, else the scale will produce
492*b1cdbd2cSJim Jagielski                                     // a bitmap in gray or Black/White (!)
493*b1cdbd2cSJim Jagielski                                     if(aBitmapEx.GetBitCount() < 24)
494*b1cdbd2cSJim Jagielski                                     {
495*b1cdbd2cSJim Jagielski                                         aBitmapEx.Convert(BMP_CONVERSION_24BIT);
496*b1cdbd2cSJim Jagielski                                     }
497*b1cdbd2cSJim Jagielski 
498*b1cdbd2cSJim Jagielski                                     aBitmapEx.Scale(aNeededBitmapSizePixel, BMP_SCALE_INTERPOLATE);
499*b1cdbd2cSJim Jagielski                                 }
500*b1cdbd2cSJim Jagielski 
501*b1cdbd2cSJim Jagielski 					            bool bPainted(false);
502*b1cdbd2cSJim Jagielski 
503*b1cdbd2cSJim Jagielski 					            if(maBColorModifierStack.count())
504*b1cdbd2cSJim Jagielski 					            {
505*b1cdbd2cSJim Jagielski                                     // when color modifier, apply to bitmap
506*b1cdbd2cSJim Jagielski 						            aBitmapEx = aBitmapEx.ModifyBitmapEx(maBColorModifierStack);
507*b1cdbd2cSJim Jagielski 
508*b1cdbd2cSJim Jagielski                                     // impModifyBitmapEx uses empty bitmap as sign to return that
509*b1cdbd2cSJim Jagielski                                     // the content will be completely replaced to mono color, use shortcut
510*b1cdbd2cSJim Jagielski 						            if(aBitmapEx.IsEmpty())
511*b1cdbd2cSJim Jagielski 						            {
512*b1cdbd2cSJim Jagielski 							            // color gets completely replaced, get it
513*b1cdbd2cSJim Jagielski 							            const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
514*b1cdbd2cSJim Jagielski 							            basegfx::B2DPolygon aPolygon(basegfx::tools::createUnitPolygon());
515*b1cdbd2cSJim Jagielski 							            aPolygon.transform(aLocalTransform);
516*b1cdbd2cSJim Jagielski 
517*b1cdbd2cSJim Jagielski 							            mpOutputDevice->SetFillColor(Color(aModifiedColor));
518*b1cdbd2cSJim Jagielski 							            mpOutputDevice->SetLineColor();
519*b1cdbd2cSJim Jagielski 							            mpOutputDevice->DrawPolygon(aPolygon);
520*b1cdbd2cSJim Jagielski 
521*b1cdbd2cSJim Jagielski 							            bPainted = true;
522*b1cdbd2cSJim Jagielski 						            }
523*b1cdbd2cSJim Jagielski 					            }
524*b1cdbd2cSJim Jagielski 
525*b1cdbd2cSJim Jagielski 					            if(!bPainted)
526*b1cdbd2cSJim Jagielski 					            {
527*b1cdbd2cSJim Jagielski                                     sal_Int32 nBLeft(basegfx::fround(aGraphicRange.getMinX()));
528*b1cdbd2cSJim Jagielski                                     sal_Int32 nBTop(basegfx::fround(aGraphicRange.getMinY()));
529*b1cdbd2cSJim Jagielski                                     const sal_Int32 nOLeft(basegfx::fround(aObjectRange.getMinX()));
530*b1cdbd2cSJim Jagielski                                     const sal_Int32 nOTop(basegfx::fround(aObjectRange.getMinY()));
531*b1cdbd2cSJim Jagielski                                     sal_Int32 nPosX(0);
532*b1cdbd2cSJim Jagielski                                     sal_Int32 nPosY(0);
533*b1cdbd2cSJim Jagielski 
534*b1cdbd2cSJim Jagielski 						            if(nBLeft > nOLeft)
535*b1cdbd2cSJim Jagielski 						            {
536*b1cdbd2cSJim Jagielski                                         const sal_Int32 nDiff((nBLeft / nBWidth) + 1);
537*b1cdbd2cSJim Jagielski 
538*b1cdbd2cSJim Jagielski                                         nPosX -= nDiff;
539*b1cdbd2cSJim Jagielski 							            nBLeft -= nDiff * nBWidth;
540*b1cdbd2cSJim Jagielski 						            }
541*b1cdbd2cSJim Jagielski 
542*b1cdbd2cSJim Jagielski 						            if(nBLeft + nBWidth <= nOLeft)
543*b1cdbd2cSJim Jagielski 						            {
544*b1cdbd2cSJim Jagielski                                         const sal_Int32 nDiff(-nBLeft / nBWidth);
545*b1cdbd2cSJim Jagielski 
546*b1cdbd2cSJim Jagielski                                         nPosX += nDiff;
547*b1cdbd2cSJim Jagielski 							            nBLeft += nDiff * nBWidth;
548*b1cdbd2cSJim Jagielski 						            }
549*b1cdbd2cSJim Jagielski 
550*b1cdbd2cSJim Jagielski 						            if(nBTop > nOTop)
551*b1cdbd2cSJim Jagielski 						            {
552*b1cdbd2cSJim Jagielski                                         const sal_Int32 nDiff((nBTop / nBHeight) + 1);
553*b1cdbd2cSJim Jagielski 
554*b1cdbd2cSJim Jagielski                                         nPosY -= nDiff;
555*b1cdbd2cSJim Jagielski 							            nBTop -= nDiff * nBHeight;
556*b1cdbd2cSJim Jagielski 						            }
557*b1cdbd2cSJim Jagielski 
558*b1cdbd2cSJim Jagielski 						            if(nBTop + nBHeight <= nOTop)
559*b1cdbd2cSJim Jagielski 						            {
560*b1cdbd2cSJim Jagielski                                         const sal_Int32 nDiff(-nBTop / nBHeight);
561*b1cdbd2cSJim Jagielski 
562*b1cdbd2cSJim Jagielski                                         nPosY += nDiff;
563*b1cdbd2cSJim Jagielski 							            nBTop += nDiff * nBHeight;
564*b1cdbd2cSJim Jagielski 						            }
565*b1cdbd2cSJim Jagielski 
566*b1cdbd2cSJim Jagielski 						            // prepare OutDev
567*b1cdbd2cSJim Jagielski 						            const Point aEmptyPoint(0, 0);
568*b1cdbd2cSJim Jagielski 						            const Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
569*b1cdbd2cSJim Jagielski 						            const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
570*b1cdbd2cSJim Jagielski 						            mpOutputDevice->EnableMapMode(false);
571*b1cdbd2cSJim Jagielski 
572*b1cdbd2cSJim Jagielski                                     // check if offset is used
573*b1cdbd2cSJim Jagielski                                     const sal_Int32 nOffsetX(basegfx::fround(rFillGraphicAttribute.getOffsetX() * nBWidth));
574*b1cdbd2cSJim Jagielski 
575*b1cdbd2cSJim Jagielski                                     if(nOffsetX)
576*b1cdbd2cSJim Jagielski                                     {
577*b1cdbd2cSJim Jagielski                                         // offset in X, so iterate over Y first and draw lines
578*b1cdbd2cSJim Jagielski                                         for(sal_Int32 nYPos(nBTop); nYPos < nOTop + nOHeight; nYPos += nBHeight, nPosY++)
579*b1cdbd2cSJim Jagielski                                         {
580*b1cdbd2cSJim Jagielski                                             for(sal_Int32 nXPos(nPosY % 2 ? nBLeft - nBWidth + nOffsetX : nBLeft);
581*b1cdbd2cSJim Jagielski                                                 nXPos < nOLeft + nOWidth; nXPos += nBWidth)
582*b1cdbd2cSJim Jagielski                                             {
583*b1cdbd2cSJim Jagielski                                                 const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
584*b1cdbd2cSJim Jagielski 
585*b1cdbd2cSJim Jagielski                                                 if(aOutRectPixel.IsOver(aVisiblePixel))
586*b1cdbd2cSJim Jagielski                                                 {
587*b1cdbd2cSJim Jagielski                                                     if(bPreScaled)
588*b1cdbd2cSJim Jagielski                                                     {
589*b1cdbd2cSJim Jagielski                                                         mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
590*b1cdbd2cSJim Jagielski                                                     }
591*b1cdbd2cSJim Jagielski                                                     else
592*b1cdbd2cSJim Jagielski                                                     {
593*b1cdbd2cSJim Jagielski                                                         mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aNeededBitmapSizePixel, aBitmapEx);
594*b1cdbd2cSJim Jagielski                                                     }
595*b1cdbd2cSJim Jagielski                                                 }
596*b1cdbd2cSJim Jagielski                                             }
597*b1cdbd2cSJim Jagielski                                         }
598*b1cdbd2cSJim Jagielski                                     }
599*b1cdbd2cSJim Jagielski                                     else
600*b1cdbd2cSJim Jagielski                                     {
601*b1cdbd2cSJim Jagielski                                         // check if offset is used
602*b1cdbd2cSJim Jagielski                                         const sal_Int32 nOffsetY(basegfx::fround(rFillGraphicAttribute.getOffsetY() * nBHeight));
603*b1cdbd2cSJim Jagielski 
604*b1cdbd2cSJim Jagielski                                         // possible offset in Y, so iterate over X first and draw columns
605*b1cdbd2cSJim Jagielski                                         for(sal_Int32 nXPos(nBLeft); nXPos < nOLeft + nOWidth; nXPos += nBWidth, nPosX++)
606*b1cdbd2cSJim Jagielski                                         {
607*b1cdbd2cSJim Jagielski                                             for(sal_Int32 nYPos(nPosX % 2 ? nBTop - nBHeight + nOffsetY : nBTop);
608*b1cdbd2cSJim Jagielski                                                 nYPos < nOTop + nOHeight; nYPos += nBHeight)
609*b1cdbd2cSJim Jagielski                                             {
610*b1cdbd2cSJim Jagielski                                                 const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
611*b1cdbd2cSJim Jagielski 
612*b1cdbd2cSJim Jagielski                                                 if(aOutRectPixel.IsOver(aVisiblePixel))
613*b1cdbd2cSJim Jagielski                                                 {
614*b1cdbd2cSJim Jagielski                                                     if(bPreScaled)
615*b1cdbd2cSJim Jagielski                                                     {
616*b1cdbd2cSJim Jagielski                                                         mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
617*b1cdbd2cSJim Jagielski                                                     }
618*b1cdbd2cSJim Jagielski                                                     else
619*b1cdbd2cSJim Jagielski                                                     {
620*b1cdbd2cSJim Jagielski                                                         mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aNeededBitmapSizePixel, aBitmapEx);
621*b1cdbd2cSJim Jagielski                                                     }
622*b1cdbd2cSJim Jagielski                                                 }
623*b1cdbd2cSJim Jagielski                                             }
624*b1cdbd2cSJim Jagielski                                         }
625*b1cdbd2cSJim Jagielski                                     }
626*b1cdbd2cSJim Jagielski 
627*b1cdbd2cSJim Jagielski 						            // restore OutDev
628*b1cdbd2cSJim Jagielski 						            mpOutputDevice->EnableMapMode(bWasEnabled);
629*b1cdbd2cSJim Jagielski                                 }
630*b1cdbd2cSJim Jagielski                             }
631*b1cdbd2cSJim Jagielski                         }
632*b1cdbd2cSJim Jagielski 				    }
633*b1cdbd2cSJim Jagielski 			    }
634*b1cdbd2cSJim Jagielski             }
635*b1cdbd2cSJim Jagielski 
636*b1cdbd2cSJim Jagielski 			if(!bPrimitiveAccepted)
637*b1cdbd2cSJim Jagielski 			{
638*b1cdbd2cSJim Jagielski 				// do not accept, use decomposition
639*b1cdbd2cSJim Jagielski 				process(rFillBitmapCandidate.get2DDecomposition(getViewInformation2D()));
640*b1cdbd2cSJim Jagielski 			}
641*b1cdbd2cSJim Jagielski 		}
642*b1cdbd2cSJim Jagielski 
643*b1cdbd2cSJim Jagielski 		// direct draw of Graphic
RenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D & rPolygonCandidate)644*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderPolyPolygonGraphicPrimitive2D(const primitive2d::PolyPolygonGraphicPrimitive2D& rPolygonCandidate)
645*b1cdbd2cSJim Jagielski 		{
646*b1cdbd2cSJim Jagielski             bool bDone(false);
647*b1cdbd2cSJim Jagielski             const basegfx::B2DPolyPolygon& rPolyPolygon = rPolygonCandidate.getB2DPolyPolygon();
648*b1cdbd2cSJim Jagielski 
649*b1cdbd2cSJim Jagielski             // #121194# Todo: check if this works
650*b1cdbd2cSJim Jagielski             if(!rPolyPolygon.count())
651*b1cdbd2cSJim Jagielski             {
652*b1cdbd2cSJim Jagielski                 // empty polyPolygon, done
653*b1cdbd2cSJim Jagielski                 bDone = true;
654*b1cdbd2cSJim Jagielski             }
655*b1cdbd2cSJim Jagielski             else
656*b1cdbd2cSJim Jagielski             {
657*b1cdbd2cSJim Jagielski                 const attribute::FillGraphicAttribute& rFillGraphicAttribute = rPolygonCandidate.getFillGraphic();
658*b1cdbd2cSJim Jagielski 
659*b1cdbd2cSJim Jagielski                 // try to catch cases where the graphic will be color-modified to a single
660*b1cdbd2cSJim Jagielski                 // color (e.g. shadow)
661*b1cdbd2cSJim Jagielski                 switch(rFillGraphicAttribute.getGraphic().GetType())
662*b1cdbd2cSJim Jagielski                 {
663*b1cdbd2cSJim Jagielski                     case GRAPHIC_GDIMETAFILE:
664*b1cdbd2cSJim Jagielski                     {
665*b1cdbd2cSJim Jagielski                         // metafiles are potentially transparent, cannot optimize, not done
666*b1cdbd2cSJim Jagielski                         break;
667*b1cdbd2cSJim Jagielski                     }
668*b1cdbd2cSJim Jagielski                     case GRAPHIC_BITMAP:
669*b1cdbd2cSJim Jagielski                     {
670*b1cdbd2cSJim Jagielski                         if(!rFillGraphicAttribute.getGraphic().IsTransparent() && !rFillGraphicAttribute.getGraphic().IsAlpha())
671*b1cdbd2cSJim Jagielski                         {
672*b1cdbd2cSJim Jagielski                             // bitmap is not transparent and has no alpha
673*b1cdbd2cSJim Jagielski                             const sal_uInt32 nBColorModifierStackCount(maBColorModifierStack.count());
674*b1cdbd2cSJim Jagielski 
675*b1cdbd2cSJim Jagielski                             if(nBColorModifierStackCount)
676*b1cdbd2cSJim Jagielski                             {
677*b1cdbd2cSJim Jagielski                                 const basegfx::BColorModifierSharedPtr& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1);
678*b1cdbd2cSJim Jagielski                                 const basegfx::BColorModifier_replace* pReplacer = dynamic_cast< const basegfx::BColorModifier_replace* >(rTopmostModifier.get());
679*b1cdbd2cSJim Jagielski 
680*b1cdbd2cSJim Jagielski                                 if(pReplacer)
681*b1cdbd2cSJim Jagielski                                 {
682*b1cdbd2cSJim Jagielski                                     // the bitmap fill is in unified color, so we can replace it with
683*b1cdbd2cSJim Jagielski                                     // a single polygon fill. The form of the fill depends on tiling
684*b1cdbd2cSJim Jagielski                                     if(rFillGraphicAttribute.getTiling())
685*b1cdbd2cSJim Jagielski                                     {
686*b1cdbd2cSJim Jagielski                                         // with tiling, fill the whole PolyPolygon with the modifier color
687*b1cdbd2cSJim Jagielski                                         basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolyPolygon);
688*b1cdbd2cSJim Jagielski 
689*b1cdbd2cSJim Jagielski                                         aLocalPolyPolygon.transform(maCurrentTransformation);
690*b1cdbd2cSJim Jagielski                                         mpOutputDevice->SetLineColor();
691*b1cdbd2cSJim Jagielski                                         mpOutputDevice->SetFillColor(Color(pReplacer->getBColor()));
692*b1cdbd2cSJim Jagielski                                         mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
693*b1cdbd2cSJim Jagielski                                     }
694*b1cdbd2cSJim Jagielski                                     else
695*b1cdbd2cSJim Jagielski                                     {
696*b1cdbd2cSJim Jagielski                                         // without tiling, only the area common to the bitmap tile and the
697*b1cdbd2cSJim Jagielski                                         // PolyPolygon is filled. Create the bitmap tile area in object
698*b1cdbd2cSJim Jagielski                                         // coordinates. For this, the object transformation needs to be created
699*b1cdbd2cSJim Jagielski                                         // from the already scaled PolyPolygon. The tile area in object
700*b1cdbd2cSJim Jagielski                                         // coordinates wil always be non-rotated, so it's not necessary to
701*b1cdbd2cSJim Jagielski                                         // work with a polygon here
702*b1cdbd2cSJim Jagielski                                         basegfx::B2DRange aTileRange(rFillGraphicAttribute.getGraphicRange());
703*b1cdbd2cSJim Jagielski                                         const basegfx::B2DRange aPolyPolygonRange(rPolyPolygon.getB2DRange());
704*b1cdbd2cSJim Jagielski                                         const basegfx::B2DHomMatrix aNewObjectTransform(
705*b1cdbd2cSJim Jagielski                                             basegfx::tools::createScaleTranslateB2DHomMatrix(
706*b1cdbd2cSJim Jagielski                                                 aPolyPolygonRange.getRange(),
707*b1cdbd2cSJim Jagielski                                                 aPolyPolygonRange.getMinimum()));
708*b1cdbd2cSJim Jagielski 
709*b1cdbd2cSJim Jagielski                                         aTileRange.transform(aNewObjectTransform);
710*b1cdbd2cSJim Jagielski 
711*b1cdbd2cSJim Jagielski                                         // now clip the object polyPolygon against the tile range
712*b1cdbd2cSJim Jagielski                                         // to get the common area
713*b1cdbd2cSJim Jagielski                                         basegfx::B2DPolyPolygon aTarget = basegfx::tools::clipPolyPolygonOnRange(
714*b1cdbd2cSJim Jagielski                                             rPolyPolygon,
715*b1cdbd2cSJim Jagielski                                             aTileRange,
716*b1cdbd2cSJim Jagielski                                             true,
717*b1cdbd2cSJim Jagielski                                             false);
718*b1cdbd2cSJim Jagielski 
719*b1cdbd2cSJim Jagielski                                         if(aTarget.count())
720*b1cdbd2cSJim Jagielski                                         {
721*b1cdbd2cSJim Jagielski                                             aTarget.transform(maCurrentTransformation);
722*b1cdbd2cSJim Jagielski                                             mpOutputDevice->SetLineColor();
723*b1cdbd2cSJim Jagielski                                             mpOutputDevice->SetFillColor(Color(pReplacer->getBColor()));
724*b1cdbd2cSJim Jagielski                                             mpOutputDevice->DrawPolyPolygon(aTarget);
725*b1cdbd2cSJim Jagielski                                         }
726*b1cdbd2cSJim Jagielski                                     }
727*b1cdbd2cSJim Jagielski 
728*b1cdbd2cSJim Jagielski                                     // simplified output executed, we are done
729*b1cdbd2cSJim Jagielski                                     bDone = true;
730*b1cdbd2cSJim Jagielski                                 }
731*b1cdbd2cSJim Jagielski                             }
732*b1cdbd2cSJim Jagielski                         }
733*b1cdbd2cSJim Jagielski                         break;
734*b1cdbd2cSJim Jagielski                     }
735*b1cdbd2cSJim Jagielski                     default: //GRAPHIC_NONE, GRAPHIC_DEFAULT
736*b1cdbd2cSJim Jagielski                     {
737*b1cdbd2cSJim Jagielski                         // empty graphic, we are done
738*b1cdbd2cSJim Jagielski                         bDone = true;
739*b1cdbd2cSJim Jagielski                         break;
740*b1cdbd2cSJim Jagielski                     }
741*b1cdbd2cSJim Jagielski                 }
742*b1cdbd2cSJim Jagielski             }
743*b1cdbd2cSJim Jagielski 
744*b1cdbd2cSJim Jagielski             if(!bDone)
745*b1cdbd2cSJim Jagielski             {
746*b1cdbd2cSJim Jagielski                 // use default decomposition
747*b1cdbd2cSJim Jagielski                 process(rPolygonCandidate.get2DDecomposition(getViewInformation2D()));
748*b1cdbd2cSJim Jagielski             }
749*b1cdbd2cSJim Jagielski         }
750*b1cdbd2cSJim Jagielski 
751*b1cdbd2cSJim Jagielski 		// mask group. Force output to VDev and create mask from given mask
RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D & rMaskCandidate)752*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderMaskPrimitive2DPixel(const primitive2d::MaskPrimitive2D& rMaskCandidate)
753*b1cdbd2cSJim Jagielski 		{
754*b1cdbd2cSJim Jagielski 			if(rMaskCandidate.getChildren().hasElements())
755*b1cdbd2cSJim Jagielski 			{
756*b1cdbd2cSJim Jagielski 				basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
757*b1cdbd2cSJim Jagielski 
758*b1cdbd2cSJim Jagielski 				if(aMask.count())
759*b1cdbd2cSJim Jagielski 				{
760*b1cdbd2cSJim Jagielski 					aMask.transform(maCurrentTransformation);
761*b1cdbd2cSJim Jagielski 					const basegfx::B2DRange aRange(basegfx::tools::getRange(aMask));
762*b1cdbd2cSJim Jagielski 					impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
763*b1cdbd2cSJim Jagielski 
764*b1cdbd2cSJim Jagielski 					if(aBufferDevice.isVisible())
765*b1cdbd2cSJim Jagielski 					{
766*b1cdbd2cSJim Jagielski 						// remember last OutDev and set to content
767*b1cdbd2cSJim Jagielski 						OutputDevice* pLastOutputDevice = mpOutputDevice;
768*b1cdbd2cSJim Jagielski 						mpOutputDevice = &aBufferDevice.getContent();
769*b1cdbd2cSJim Jagielski 
770*b1cdbd2cSJim Jagielski 						// paint to it
771*b1cdbd2cSJim Jagielski 						process(rMaskCandidate.getChildren());
772*b1cdbd2cSJim Jagielski 
773*b1cdbd2cSJim Jagielski 						// back to old OutDev
774*b1cdbd2cSJim Jagielski 						mpOutputDevice = pLastOutputDevice;
775*b1cdbd2cSJim Jagielski 
776*b1cdbd2cSJim Jagielski 					    // draw mask
777*b1cdbd2cSJim Jagielski                         if(getOptionsDrawinglayer().IsAntiAliasing())
778*b1cdbd2cSJim Jagielski                         {
779*b1cdbd2cSJim Jagielski                             // with AA, use 8bit AlphaMask to get nice borders
780*b1cdbd2cSJim Jagielski 						    VirtualDevice& rTransparence = aBufferDevice.getTransparence();
781*b1cdbd2cSJim Jagielski 						    rTransparence.SetLineColor();
782*b1cdbd2cSJim Jagielski 						    rTransparence.SetFillColor(COL_BLACK);
783*b1cdbd2cSJim Jagielski 						    rTransparence.DrawPolyPolygon(aMask);
784*b1cdbd2cSJim Jagielski 
785*b1cdbd2cSJim Jagielski 						    // dump buffer to outdev
786*b1cdbd2cSJim Jagielski 						    aBufferDevice.paint();
787*b1cdbd2cSJim Jagielski                         }
788*b1cdbd2cSJim Jagielski                         else
789*b1cdbd2cSJim Jagielski                         {
790*b1cdbd2cSJim Jagielski                             // No AA, use 1bit mask
791*b1cdbd2cSJim Jagielski 						    VirtualDevice& rMask = aBufferDevice.getMask();
792*b1cdbd2cSJim Jagielski 						    rMask.SetLineColor();
793*b1cdbd2cSJim Jagielski 						    rMask.SetFillColor(COL_BLACK);
794*b1cdbd2cSJim Jagielski 						    rMask.DrawPolyPolygon(aMask);
795*b1cdbd2cSJim Jagielski 
796*b1cdbd2cSJim Jagielski 						    // dump buffer to outdev
797*b1cdbd2cSJim Jagielski 						    aBufferDevice.paint();
798*b1cdbd2cSJim Jagielski                         }
799*b1cdbd2cSJim Jagielski 					}
800*b1cdbd2cSJim Jagielski 				}
801*b1cdbd2cSJim Jagielski 			}
802*b1cdbd2cSJim Jagielski 		}
803*b1cdbd2cSJim Jagielski 
804*b1cdbd2cSJim Jagielski 		// modified color group. Force output to unified color.
RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D & rModifiedCandidate)805*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate)
806*b1cdbd2cSJim Jagielski 		{
807*b1cdbd2cSJim Jagielski 			if(rModifiedCandidate.getChildren().hasElements())
808*b1cdbd2cSJim Jagielski 			{
809*b1cdbd2cSJim Jagielski 				maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
810*b1cdbd2cSJim Jagielski 				process(rModifiedCandidate.getChildren());
811*b1cdbd2cSJim Jagielski 				maBColorModifierStack.pop();
812*b1cdbd2cSJim Jagielski 			}
813*b1cdbd2cSJim Jagielski 		}
814*b1cdbd2cSJim Jagielski 
815*b1cdbd2cSJim Jagielski 		// unified sub-transparence. Draw to VDev first.
RenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D & rTransCandidate)816*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderUnifiedTransparencePrimitive2D(const primitive2d::UnifiedTransparencePrimitive2D& rTransCandidate)
817*b1cdbd2cSJim Jagielski 		{
818*b1cdbd2cSJim Jagielski             static bool bForceToDecomposition(false);
819*b1cdbd2cSJim Jagielski 
820*b1cdbd2cSJim Jagielski             if(rTransCandidate.getChildren().hasElements())
821*b1cdbd2cSJim Jagielski             {
822*b1cdbd2cSJim Jagielski                 if(bForceToDecomposition)
823*b1cdbd2cSJim Jagielski                 {
824*b1cdbd2cSJim Jagielski     			    // use decomposition
825*b1cdbd2cSJim Jagielski 	    		    process(rTransCandidate.get2DDecomposition(getViewInformation2D()));
826*b1cdbd2cSJim Jagielski                 }
827*b1cdbd2cSJim Jagielski                 else
828*b1cdbd2cSJim Jagielski                 {
829*b1cdbd2cSJim Jagielski 			        if(0.0 == rTransCandidate.getTransparence())
830*b1cdbd2cSJim Jagielski 			        {
831*b1cdbd2cSJim Jagielski 				        // no transparence used, so just use the content
832*b1cdbd2cSJim Jagielski     	    		    process(rTransCandidate.getChildren());
833*b1cdbd2cSJim Jagielski 			        }
834*b1cdbd2cSJim Jagielski 			        else if(rTransCandidate.getTransparence() > 0.0 && rTransCandidate.getTransparence() < 1.0)
835*b1cdbd2cSJim Jagielski 			        {
836*b1cdbd2cSJim Jagielski                         // transparence is in visible range
837*b1cdbd2cSJim Jagielski 				        basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D()));
838*b1cdbd2cSJim Jagielski 				        aRange.transform(maCurrentTransformation);
839*b1cdbd2cSJim Jagielski 				        impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
840*b1cdbd2cSJim Jagielski 
841*b1cdbd2cSJim Jagielski 				        if(aBufferDevice.isVisible())
842*b1cdbd2cSJim Jagielski 				        {
843*b1cdbd2cSJim Jagielski 					        // remember last OutDev and set to content
844*b1cdbd2cSJim Jagielski 					        OutputDevice* pLastOutputDevice = mpOutputDevice;
845*b1cdbd2cSJim Jagielski 					        mpOutputDevice = &aBufferDevice.getContent();
846*b1cdbd2cSJim Jagielski 
847*b1cdbd2cSJim Jagielski 					        // paint content to it
848*b1cdbd2cSJim Jagielski 					        process(rTransCandidate.getChildren());
849*b1cdbd2cSJim Jagielski 
850*b1cdbd2cSJim Jagielski 					        // back to old OutDev
851*b1cdbd2cSJim Jagielski 					        mpOutputDevice = pLastOutputDevice;
852*b1cdbd2cSJim Jagielski 
853*b1cdbd2cSJim Jagielski 					        // dump buffer to outdev using given transparence
854*b1cdbd2cSJim Jagielski 					        aBufferDevice.paint(rTransCandidate.getTransparence());
855*b1cdbd2cSJim Jagielski 				        }
856*b1cdbd2cSJim Jagielski 			        }
857*b1cdbd2cSJim Jagielski                 }
858*b1cdbd2cSJim Jagielski             }
859*b1cdbd2cSJim Jagielski 		}
860*b1cdbd2cSJim Jagielski 
861*b1cdbd2cSJim Jagielski 		// sub-transparence group. Draw to VDev first.
RenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D & rTransCandidate)862*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderTransparencePrimitive2D(const primitive2d::TransparencePrimitive2D& rTransCandidate)
863*b1cdbd2cSJim Jagielski 		{
864*b1cdbd2cSJim Jagielski 			if(rTransCandidate.getChildren().hasElements())
865*b1cdbd2cSJim Jagielski 			{
866*b1cdbd2cSJim Jagielski 				basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D()));
867*b1cdbd2cSJim Jagielski 				aRange.transform(maCurrentTransformation);
868*b1cdbd2cSJim Jagielski 				impBufferDevice aBufferDevice(*mpOutputDevice, aRange, true);
869*b1cdbd2cSJim Jagielski 
870*b1cdbd2cSJim Jagielski 				if(aBufferDevice.isVisible())
871*b1cdbd2cSJim Jagielski 				{
872*b1cdbd2cSJim Jagielski 					// remember last OutDev and set to content
873*b1cdbd2cSJim Jagielski 					OutputDevice* pLastOutputDevice = mpOutputDevice;
874*b1cdbd2cSJim Jagielski 					mpOutputDevice = &aBufferDevice.getContent();
875*b1cdbd2cSJim Jagielski 
876*b1cdbd2cSJim Jagielski 					// paint content to it
877*b1cdbd2cSJim Jagielski 					process(rTransCandidate.getChildren());
878*b1cdbd2cSJim Jagielski 
879*b1cdbd2cSJim Jagielski 					// set to mask
880*b1cdbd2cSJim Jagielski 					mpOutputDevice = &aBufferDevice.getTransparence();
881*b1cdbd2cSJim Jagielski 
882*b1cdbd2cSJim Jagielski 					// when painting transparence masks, reset the color stack
883*b1cdbd2cSJim Jagielski 					basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
884*b1cdbd2cSJim Jagielski 					maBColorModifierStack = basegfx::BColorModifierStack();
885*b1cdbd2cSJim Jagielski 
886*b1cdbd2cSJim Jagielski 					// paint mask to it (always with transparence intensities, evtl. with AA)
887*b1cdbd2cSJim Jagielski 					process(rTransCandidate.getTransparence());
888*b1cdbd2cSJim Jagielski 
889*b1cdbd2cSJim Jagielski 					// back to old color stack
890*b1cdbd2cSJim Jagielski 					maBColorModifierStack = aLastBColorModifierStack;
891*b1cdbd2cSJim Jagielski 
892*b1cdbd2cSJim Jagielski 					// back to old OutDev
893*b1cdbd2cSJim Jagielski 					mpOutputDevice = pLastOutputDevice;
894*b1cdbd2cSJim Jagielski 
895*b1cdbd2cSJim Jagielski 					// dump buffer to outdev
896*b1cdbd2cSJim Jagielski 					aBufferDevice.paint();
897*b1cdbd2cSJim Jagielski 				}
898*b1cdbd2cSJim Jagielski 			}
899*b1cdbd2cSJim Jagielski 		}
900*b1cdbd2cSJim Jagielski 
901*b1cdbd2cSJim Jagielski 		// transform group.
RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D & rTransformCandidate)902*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate)
903*b1cdbd2cSJim Jagielski 		{
904*b1cdbd2cSJim Jagielski 			// remember current transformation and ViewInformation
905*b1cdbd2cSJim Jagielski 			const basegfx::B2DHomMatrix aLastCurrentTransformation(maCurrentTransformation);
906*b1cdbd2cSJim Jagielski             const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
907*b1cdbd2cSJim Jagielski 
908*b1cdbd2cSJim Jagielski 			// create new transformations for CurrentTransformation
909*b1cdbd2cSJim Jagielski             // and for local ViewInformation2D
910*b1cdbd2cSJim Jagielski 			maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation();
911*b1cdbd2cSJim Jagielski             const geometry::ViewInformation2D aViewInformation2D(
912*b1cdbd2cSJim Jagielski                 getViewInformation2D().getObjectTransformation() * rTransformCandidate.getTransformation(),
913*b1cdbd2cSJim Jagielski                 getViewInformation2D().getViewTransformation(),
914*b1cdbd2cSJim Jagielski                 getViewInformation2D().getViewport(),
915*b1cdbd2cSJim Jagielski 				getViewInformation2D().getVisualizedPage(),
916*b1cdbd2cSJim Jagielski                 getViewInformation2D().getViewTime(),
917*b1cdbd2cSJim Jagielski 				getViewInformation2D().getExtendedInformationSequence());
918*b1cdbd2cSJim Jagielski 			updateViewInformation(aViewInformation2D);
919*b1cdbd2cSJim Jagielski 
920*b1cdbd2cSJim Jagielski 			// proccess content
921*b1cdbd2cSJim Jagielski 			process(rTransformCandidate.getChildren());
922*b1cdbd2cSJim Jagielski 
923*b1cdbd2cSJim Jagielski 			// restore transformations
924*b1cdbd2cSJim Jagielski 			maCurrentTransformation = aLastCurrentTransformation;
925*b1cdbd2cSJim Jagielski             updateViewInformation(aLastViewInformation2D);
926*b1cdbd2cSJim Jagielski 		}
927*b1cdbd2cSJim Jagielski 
928*b1cdbd2cSJim Jagielski 		// new XDrawPage for ViewInformation2D
RenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D & rPagePreviewCandidate)929*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderPagePreviewPrimitive2D(const primitive2d::PagePreviewPrimitive2D& rPagePreviewCandidate)
930*b1cdbd2cSJim Jagielski 		{
931*b1cdbd2cSJim Jagielski 			// remember current transformation and ViewInformation
932*b1cdbd2cSJim Jagielski             const geometry::ViewInformation2D aLastViewInformation2D(getViewInformation2D());
933*b1cdbd2cSJim Jagielski 
934*b1cdbd2cSJim Jagielski 			// create new local ViewInformation2D
935*b1cdbd2cSJim Jagielski             const geometry::ViewInformation2D aViewInformation2D(
936*b1cdbd2cSJim Jagielski                 getViewInformation2D().getObjectTransformation(),
937*b1cdbd2cSJim Jagielski                 getViewInformation2D().getViewTransformation(),
938*b1cdbd2cSJim Jagielski                 getViewInformation2D().getViewport(),
939*b1cdbd2cSJim Jagielski 				rPagePreviewCandidate.getXDrawPage(),
940*b1cdbd2cSJim Jagielski                 getViewInformation2D().getViewTime(),
941*b1cdbd2cSJim Jagielski 				getViewInformation2D().getExtendedInformationSequence());
942*b1cdbd2cSJim Jagielski 			updateViewInformation(aViewInformation2D);
943*b1cdbd2cSJim Jagielski 
944*b1cdbd2cSJim Jagielski 			// proccess decomposed content
945*b1cdbd2cSJim Jagielski 			process(rPagePreviewCandidate.get2DDecomposition(getViewInformation2D()));
946*b1cdbd2cSJim Jagielski 
947*b1cdbd2cSJim Jagielski 			// restore transformations
948*b1cdbd2cSJim Jagielski             updateViewInformation(aLastViewInformation2D);
949*b1cdbd2cSJim Jagielski 		}
950*b1cdbd2cSJim Jagielski 
951*b1cdbd2cSJim Jagielski 		// marker
RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D & rMarkArrayCandidate)952*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D& rMarkArrayCandidate)
953*b1cdbd2cSJim Jagielski 		{
954*b1cdbd2cSJim Jagielski             static bool bCheckCompleteMarkerDecompose(false);
955*b1cdbd2cSJim Jagielski             if(bCheckCompleteMarkerDecompose)
956*b1cdbd2cSJim Jagielski             {
957*b1cdbd2cSJim Jagielski 			    process(rMarkArrayCandidate.get2DDecomposition(getViewInformation2D()));
958*b1cdbd2cSJim Jagielski                 return;
959*b1cdbd2cSJim Jagielski             }
960*b1cdbd2cSJim Jagielski 
961*b1cdbd2cSJim Jagielski 			// get data
962*b1cdbd2cSJim Jagielski 	        const std::vector< basegfx::B2DPoint >& rPositions = rMarkArrayCandidate.getPositions();
963*b1cdbd2cSJim Jagielski 			const sal_uInt32 nCount(rPositions.size());
964*b1cdbd2cSJim Jagielski 
965*b1cdbd2cSJim Jagielski 			if(nCount && !rMarkArrayCandidate.getMarker().IsEmpty())
966*b1cdbd2cSJim Jagielski 			{
967*b1cdbd2cSJim Jagielski 				// get pixel size
968*b1cdbd2cSJim Jagielski 				const BitmapEx& rMarker(rMarkArrayCandidate.getMarker());
969*b1cdbd2cSJim Jagielski 				const Size aBitmapSize(rMarker.GetSizePixel());
970*b1cdbd2cSJim Jagielski 
971*b1cdbd2cSJim Jagielski 				if(aBitmapSize.Width() && aBitmapSize.Height())
972*b1cdbd2cSJim Jagielski 				{
973*b1cdbd2cSJim Jagielski 					// get discrete half size
974*b1cdbd2cSJim Jagielski 					const basegfx::B2DVector aDiscreteHalfSize(
975*b1cdbd2cSJim Jagielski                         (aBitmapSize.getWidth() - 1.0) * 0.5,
976*b1cdbd2cSJim Jagielski                         (aBitmapSize.getHeight() - 1.0) * 0.5);
977*b1cdbd2cSJim Jagielski 			        const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
978*b1cdbd2cSJim Jagielski 
979*b1cdbd2cSJim Jagielski                     // do not forget evtl. moved origin in target device MapMode when
980*b1cdbd2cSJim Jagielski                     // switching it off; it would be missing and lead to wrong positions.
981*b1cdbd2cSJim Jagielski                     // All his could be done using logic sizes and coordinates, too, but
982*b1cdbd2cSJim Jagielski                     // we want a 1:1 bitmap rendering here, so it's more safe and faster
983*b1cdbd2cSJim Jagielski                     // to work with switching off MapMode usage completely.
984*b1cdbd2cSJim Jagielski                     const Point aOrigin(mpOutputDevice->GetMapMode().GetOrigin());
985*b1cdbd2cSJim Jagielski 
986*b1cdbd2cSJim Jagielski                     mpOutputDevice->EnableMapMode(false);
987*b1cdbd2cSJim Jagielski 
988*b1cdbd2cSJim Jagielski 					for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++)
989*b1cdbd2cSJim Jagielski 				    {
990*b1cdbd2cSJim Jagielski 					    const basegfx::B2DPoint aDiscreteTopLeft((maCurrentTransformation * (*aIter)) - aDiscreteHalfSize);
991*b1cdbd2cSJim Jagielski                         const Point aDiscretePoint(basegfx::fround(aDiscreteTopLeft.getX()), basegfx::fround(aDiscreteTopLeft.getY()));
992*b1cdbd2cSJim Jagielski 
993*b1cdbd2cSJim Jagielski 						mpOutputDevice->DrawBitmapEx(aDiscretePoint + aOrigin, rMarker);
994*b1cdbd2cSJim Jagielski 					}
995*b1cdbd2cSJim Jagielski 
996*b1cdbd2cSJim Jagielski 			        mpOutputDevice->EnableMapMode(bWasEnabled);
997*b1cdbd2cSJim Jagielski 				}
998*b1cdbd2cSJim Jagielski 			}
999*b1cdbd2cSJim Jagielski 		}
1000*b1cdbd2cSJim Jagielski 
1001*b1cdbd2cSJim Jagielski 		// point
RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D & rPointArrayCandidate)1002*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderPointArrayPrimitive2D(const primitive2d::PointArrayPrimitive2D& rPointArrayCandidate)
1003*b1cdbd2cSJim Jagielski 		{
1004*b1cdbd2cSJim Jagielski 			const std::vector< basegfx::B2DPoint >& rPositions = rPointArrayCandidate.getPositions();
1005*b1cdbd2cSJim Jagielski 			const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rPointArrayCandidate.getRGBColor()));
1006*b1cdbd2cSJim Jagielski 			const Color aVCLColor(aRGBColor);
1007*b1cdbd2cSJim Jagielski 
1008*b1cdbd2cSJim Jagielski 			for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++)
1009*b1cdbd2cSJim Jagielski 			{
1010*b1cdbd2cSJim Jagielski 				const basegfx::B2DPoint aViewPosition(maCurrentTransformation * (*aIter));
1011*b1cdbd2cSJim Jagielski 				const Point aPos(basegfx::fround(aViewPosition.getX()), basegfx::fround(aViewPosition.getY()));
1012*b1cdbd2cSJim Jagielski 
1013*b1cdbd2cSJim Jagielski 				mpOutputDevice->DrawPixel(aPos, aVCLColor);
1014*b1cdbd2cSJim Jagielski 			}
1015*b1cdbd2cSJim Jagielski 		}
1016*b1cdbd2cSJim Jagielski 
RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D & rPolygonStrokeCandidate)1017*b1cdbd2cSJim Jagielski 		void VclProcessor2D::RenderPolygonStrokePrimitive2D(const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokeCandidate)
1018*b1cdbd2cSJim Jagielski 		{
1019*b1cdbd2cSJim Jagielski             // #i101491# method restructured to clearly use the DrawPolyLine
1020*b1cdbd2cSJim Jagielski             // calls starting from a deined line width
1021*b1cdbd2cSJim Jagielski 			const attribute::LineAttribute& rLineAttribute = rPolygonStrokeCandidate.getLineAttribute();
1022*b1cdbd2cSJim Jagielski 			const double fLineWidth(rLineAttribute.getWidth());
1023*b1cdbd2cSJim Jagielski 			bool bDone(false);
1024*b1cdbd2cSJim Jagielski 
1025*b1cdbd2cSJim Jagielski 			if(basegfx::fTools::more(fLineWidth, 0.0))
1026*b1cdbd2cSJim Jagielski 			{
1027*b1cdbd2cSJim Jagielski 				const basegfx::B2DVector aDiscreteUnit(maCurrentTransformation * basegfx::B2DVector(fLineWidth, 0.0));
1028*b1cdbd2cSJim Jagielski 				const double fDiscreteLineWidth(aDiscreteUnit.getLength());
1029*b1cdbd2cSJim Jagielski 				const attribute::StrokeAttribute& rStrokeAttribute = rPolygonStrokeCandidate.getStrokeAttribute();
1030*b1cdbd2cSJim Jagielski 				const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rLineAttribute.getColor()));
1031*b1cdbd2cSJim Jagielski 				basegfx::B2DPolyPolygon aHairlinePolyPolygon;
1032*b1cdbd2cSJim Jagielski 
1033*b1cdbd2cSJim Jagielski 				mpOutputDevice->SetLineColor(Color(aHairlineColor));
1034*b1cdbd2cSJim Jagielski 				mpOutputDevice->SetFillColor();
1035*b1cdbd2cSJim Jagielski 
1036*b1cdbd2cSJim Jagielski 				if(0.0 == rStrokeAttribute.getFullDotDashLen())
1037*b1cdbd2cSJim Jagielski 				{
1038*b1cdbd2cSJim Jagielski 					// no line dashing, just copy
1039*b1cdbd2cSJim Jagielski 					aHairlinePolyPolygon.append(rPolygonStrokeCandidate.getB2DPolygon());
1040*b1cdbd2cSJim Jagielski 				}
1041*b1cdbd2cSJim Jagielski 				else
1042*b1cdbd2cSJim Jagielski 				{
1043*b1cdbd2cSJim Jagielski 					// else apply LineStyle
1044*b1cdbd2cSJim Jagielski 					basegfx::tools::applyLineDashing(rPolygonStrokeCandidate.getB2DPolygon(),
1045*b1cdbd2cSJim Jagielski 						rStrokeAttribute.getDotDashArray(),
1046*b1cdbd2cSJim Jagielski 						&aHairlinePolyPolygon, 0, rStrokeAttribute.getFullDotDashLen());
1047*b1cdbd2cSJim Jagielski 				}
1048*b1cdbd2cSJim Jagielski 
1049*b1cdbd2cSJim Jagielski 				const sal_uInt32 nCount(aHairlinePolyPolygon.count());
1050*b1cdbd2cSJim Jagielski 
1051*b1cdbd2cSJim Jagielski 				if(nCount)
1052*b1cdbd2cSJim Jagielski 				{
1053*b1cdbd2cSJim Jagielski                     const bool bAntiAliased(getOptionsDrawinglayer().IsAntiAliasing());
1054*b1cdbd2cSJim Jagielski                     aHairlinePolyPolygon.transform(maCurrentTransformation);
1055*b1cdbd2cSJim Jagielski 
1056*b1cdbd2cSJim Jagielski                     if(bAntiAliased)
1057*b1cdbd2cSJim Jagielski                     {
1058*b1cdbd2cSJim Jagielski                         if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 1.0))
1059*b1cdbd2cSJim Jagielski                         {
1060*b1cdbd2cSJim Jagielski                             // line in range ]0.0 .. 1.0[
1061*b1cdbd2cSJim Jagielski                             // paint as simple hairline
1062*b1cdbd2cSJim Jagielski                             for(sal_uInt32 a(0); a < nCount; a++)
1063*b1cdbd2cSJim Jagielski                             {
1064*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aHairlinePolyPolygon.getB2DPolygon(a), 0.0);
1065*b1cdbd2cSJim Jagielski                             }
1066*b1cdbd2cSJim Jagielski 
1067*b1cdbd2cSJim Jagielski                             bDone = true;
1068*b1cdbd2cSJim Jagielski                         }
1069*b1cdbd2cSJim Jagielski                         else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 2.0))
1070*b1cdbd2cSJim Jagielski                         {
1071*b1cdbd2cSJim Jagielski                             // line in range [1.0 .. 2.0[
1072*b1cdbd2cSJim Jagielski                             // paint as 2x2 with dynamic line distance
1073*b1cdbd2cSJim Jagielski                             basegfx::B2DHomMatrix aMat;
1074*b1cdbd2cSJim Jagielski                             const double fDistance(fDiscreteLineWidth - 1.0);
1075*b1cdbd2cSJim Jagielski                             const double fHalfDistance(fDistance * 0.5);
1076*b1cdbd2cSJim Jagielski 
1077*b1cdbd2cSJim Jagielski                             for(sal_uInt32 a(0); a < nCount; a++)
1078*b1cdbd2cSJim Jagielski                             {
1079*b1cdbd2cSJim Jagielski                                 basegfx::B2DPolygon aCandidate(aHairlinePolyPolygon.getB2DPolygon(a));
1080*b1cdbd2cSJim Jagielski 
1081*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, -fHalfDistance);
1082*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, -fHalfDistance);
1083*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1084*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1085*b1cdbd2cSJim Jagielski 
1086*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, fDistance);
1087*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, 0.0);
1088*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1089*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1090*b1cdbd2cSJim Jagielski 
1091*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, 0.0);
1092*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, fDistance);
1093*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1094*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1095*b1cdbd2cSJim Jagielski 
1096*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, -fDistance);
1097*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, 0.0);
1098*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1099*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1100*b1cdbd2cSJim Jagielski                             }
1101*b1cdbd2cSJim Jagielski 
1102*b1cdbd2cSJim Jagielski                             bDone = true;
1103*b1cdbd2cSJim Jagielski                         }
1104*b1cdbd2cSJim Jagielski                         else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 3.0))
1105*b1cdbd2cSJim Jagielski                         {
1106*b1cdbd2cSJim Jagielski                             // line in range [2.0 .. 3.0]
1107*b1cdbd2cSJim Jagielski                             // paint as cross in a 3x3  with dynamic line distance
1108*b1cdbd2cSJim Jagielski                             basegfx::B2DHomMatrix aMat;
1109*b1cdbd2cSJim Jagielski                             const double fDistance((fDiscreteLineWidth - 1.0) * 0.5);
1110*b1cdbd2cSJim Jagielski 
1111*b1cdbd2cSJim Jagielski                             for(sal_uInt32 a(0); a < nCount; a++)
1112*b1cdbd2cSJim Jagielski                             {
1113*b1cdbd2cSJim Jagielski                                 basegfx::B2DPolygon aCandidate(aHairlinePolyPolygon.getB2DPolygon(a));
1114*b1cdbd2cSJim Jagielski 
1115*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1116*b1cdbd2cSJim Jagielski 
1117*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, -fDistance);
1118*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, 0.0);
1119*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1120*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1121*b1cdbd2cSJim Jagielski 
1122*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, fDistance);
1123*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, -fDistance);
1124*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1125*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1126*b1cdbd2cSJim Jagielski 
1127*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, fDistance);
1128*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, fDistance);
1129*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1130*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1131*b1cdbd2cSJim Jagielski 
1132*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, -fDistance);
1133*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, fDistance);
1134*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1135*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1136*b1cdbd2cSJim Jagielski                             }
1137*b1cdbd2cSJim Jagielski 
1138*b1cdbd2cSJim Jagielski                             bDone = true;
1139*b1cdbd2cSJim Jagielski                         }
1140*b1cdbd2cSJim Jagielski                         else
1141*b1cdbd2cSJim Jagielski                         {
1142*b1cdbd2cSJim Jagielski                             // #i101491# line width above 3.0
1143*b1cdbd2cSJim Jagielski                         }
1144*b1cdbd2cSJim Jagielski                     }
1145*b1cdbd2cSJim Jagielski                     else
1146*b1cdbd2cSJim Jagielski                     {
1147*b1cdbd2cSJim Jagielski                         if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 1.5))
1148*b1cdbd2cSJim Jagielski                         {
1149*b1cdbd2cSJim Jagielski                             // line width below 1.5, draw the basic hairline polygon
1150*b1cdbd2cSJim Jagielski                             for(sal_uInt32 a(0); a < nCount; a++)
1151*b1cdbd2cSJim Jagielski                             {
1152*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aHairlinePolyPolygon.getB2DPolygon(a), 0.0);
1153*b1cdbd2cSJim Jagielski                             }
1154*b1cdbd2cSJim Jagielski 
1155*b1cdbd2cSJim Jagielski                             bDone = true;
1156*b1cdbd2cSJim Jagielski                         }
1157*b1cdbd2cSJim Jagielski                         else if(basegfx::fTools::lessOrEqual(fDiscreteLineWidth, 2.5))
1158*b1cdbd2cSJim Jagielski                         {
1159*b1cdbd2cSJim Jagielski                             // line width is in range ]1.5 .. 2.5], use four hairlines
1160*b1cdbd2cSJim Jagielski                             // drawn in a square
1161*b1cdbd2cSJim Jagielski                             for(sal_uInt32 a(0); a < nCount; a++)
1162*b1cdbd2cSJim Jagielski                             {
1163*b1cdbd2cSJim Jagielski                                 basegfx::B2DPolygon aCandidate(aHairlinePolyPolygon.getB2DPolygon(a));
1164*b1cdbd2cSJim Jagielski                                 basegfx::B2DHomMatrix aMat;
1165*b1cdbd2cSJim Jagielski 
1166*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1167*b1cdbd2cSJim Jagielski 
1168*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, 1.0);
1169*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, 0.0);
1170*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1171*b1cdbd2cSJim Jagielski 
1172*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1173*b1cdbd2cSJim Jagielski 
1174*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, 0.0);
1175*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, 1.0);
1176*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1177*b1cdbd2cSJim Jagielski 
1178*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1179*b1cdbd2cSJim Jagielski 
1180*b1cdbd2cSJim Jagielski                                 aMat.set(0, 2, -1.0);
1181*b1cdbd2cSJim Jagielski                                 aMat.set(1, 2, 0.0);
1182*b1cdbd2cSJim Jagielski                                 aCandidate.transform(aMat);
1183*b1cdbd2cSJim Jagielski 
1184*b1cdbd2cSJim Jagielski                                 mpOutputDevice->DrawPolyLine(aCandidate, 0.0);
1185*b1cdbd2cSJim Jagielski                             }
1186*b1cdbd2cSJim Jagielski 
1187*b1cdbd2cSJim Jagielski                             bDone = true;
1188*b1cdbd2cSJim Jagielski                         }
1189*b1cdbd2cSJim Jagielski                         else
1190*b1cdbd2cSJim Jagielski                         {
1191*b1cdbd2cSJim Jagielski                             // #i101491# line width is above 2.5
1192*b1cdbd2cSJim Jagielski                         }
1193*b1cdbd2cSJim Jagielski                     }
1194*b1cdbd2cSJim Jagielski 
1195*b1cdbd2cSJim Jagielski                     if(!bDone && rPolygonStrokeCandidate.getB2DPolygon().count() > 1000)
1196*b1cdbd2cSJim Jagielski                     {
1197*b1cdbd2cSJim Jagielski                         // #i101491# If the polygon complexity uses more than a given amount, do
1198*b1cdbd2cSJim Jagielski                         // use OuputDevice::DrawPolyLine directly; this will avoid buffering all
1199*b1cdbd2cSJim Jagielski                         // decompositions in primtives (memory) and fallback to old line painting
1200*b1cdbd2cSJim Jagielski                         // for very complex polygons, too
1201*b1cdbd2cSJim Jagielski                         for(sal_uInt32 a(0); a < nCount; a++)
1202*b1cdbd2cSJim Jagielski                         {
1203*b1cdbd2cSJim Jagielski                             mpOutputDevice->DrawPolyLine(
1204*b1cdbd2cSJim Jagielski                                 aHairlinePolyPolygon.getB2DPolygon(a),
1205*b1cdbd2cSJim Jagielski                                 fDiscreteLineWidth,
1206*b1cdbd2cSJim Jagielski                                 rLineAttribute.getLineJoin(),
1207*b1cdbd2cSJim Jagielski                                 rLineAttribute.getLineCap());
1208*b1cdbd2cSJim Jagielski                         }
1209*b1cdbd2cSJim Jagielski 
1210*b1cdbd2cSJim Jagielski                         bDone = true;
1211*b1cdbd2cSJim Jagielski                     }
1212*b1cdbd2cSJim Jagielski                 }
1213*b1cdbd2cSJim Jagielski             }
1214*b1cdbd2cSJim Jagielski 
1215*b1cdbd2cSJim Jagielski 			if(!bDone)
1216*b1cdbd2cSJim Jagielski             {
1217*b1cdbd2cSJim Jagielski                 // remeber that we enter a PolygonStrokePrimitive2D decomposition,
1218*b1cdbd2cSJim Jagielski                 // used for AA thick line drawing
1219*b1cdbd2cSJim Jagielski                 mnPolygonStrokePrimitive2D++;
1220*b1cdbd2cSJim Jagielski 
1221*b1cdbd2cSJim Jagielski                 // line width is big enough for standard filled polygon visualisation or zero
1222*b1cdbd2cSJim Jagielski 				process(rPolygonStrokeCandidate.get2DDecomposition(getViewInformation2D()));
1223*b1cdbd2cSJim Jagielski 
1224*b1cdbd2cSJim Jagielski                 // leave PolygonStrokePrimitive2D
1225*b1cdbd2cSJim Jagielski                 mnPolygonStrokePrimitive2D--;
1226*b1cdbd2cSJim Jagielski             }
1227*b1cdbd2cSJim Jagielski 		}
1228*b1cdbd2cSJim Jagielski 
RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D & rEpsPrimitive2D)1229*b1cdbd2cSJim Jagielski         void VclProcessor2D::RenderEpsPrimitive2D(const primitive2d::EpsPrimitive2D& rEpsPrimitive2D)
1230*b1cdbd2cSJim Jagielski         {
1231*b1cdbd2cSJim Jagielski             // The new decomposition of Metafiles made it necessary to add an Eps
1232*b1cdbd2cSJim Jagielski             // primitive to handle embedded Eps data. On some devices, this can be
1233*b1cdbd2cSJim Jagielski             // painted directly (mac, printer).
1234*b1cdbd2cSJim Jagielski             // To be able to handle the replacement correctly, i need to handle it myself
1235*b1cdbd2cSJim Jagielski             // since DrawEPS will not be able e.g. to rotate the replacement. To be able
1236*b1cdbd2cSJim Jagielski             // to do that, i added a boolean return to OutputDevice::DrawEPS(..)
1237*b1cdbd2cSJim Jagielski             // to know when EPS was handled directly already.
1238*b1cdbd2cSJim Jagielski 			basegfx::B2DRange aRange(0.0, 0.0, 1.0, 1.0);
1239*b1cdbd2cSJim Jagielski             aRange.transform(maCurrentTransformation * rEpsPrimitive2D.getEpsTransform());
1240*b1cdbd2cSJim Jagielski 
1241*b1cdbd2cSJim Jagielski             if(!aRange.isEmpty())
1242*b1cdbd2cSJim Jagielski             {
1243*b1cdbd2cSJim Jagielski                 const Rectangle aRectangle(
1244*b1cdbd2cSJim Jagielski 				    (sal_Int32)floor(aRange.getMinX()), (sal_Int32)floor(aRange.getMinY()),
1245*b1cdbd2cSJim Jagielski 				    (sal_Int32)ceil(aRange.getMaxX()), (sal_Int32)ceil(aRange.getMaxY()));
1246*b1cdbd2cSJim Jagielski 
1247*b1cdbd2cSJim Jagielski                 if(!aRectangle.IsEmpty())
1248*b1cdbd2cSJim Jagielski                 {
1249*b1cdbd2cSJim Jagielski                     // try to paint EPS directly without fallback visualisation
1250*b1cdbd2cSJim Jagielski                     const bool bEPSPaintedDirectly(mpOutputDevice->DrawEPS(
1251*b1cdbd2cSJim Jagielski                         aRectangle.TopLeft(),
1252*b1cdbd2cSJim Jagielski                         aRectangle.GetSize(),
1253*b1cdbd2cSJim Jagielski                         rEpsPrimitive2D.getGfxLink(),
1254*b1cdbd2cSJim Jagielski                         0));
1255*b1cdbd2cSJim Jagielski 
1256*b1cdbd2cSJim Jagielski                     if(!bEPSPaintedDirectly)
1257*b1cdbd2cSJim Jagielski                     {
1258*b1cdbd2cSJim Jagielski                         // use the decomposition which will correctly handle the
1259*b1cdbd2cSJim Jagielski                         // fallback visualisation using full transformation (e.g. rotation)
1260*b1cdbd2cSJim Jagielski         				process(rEpsPrimitive2D.get2DDecomposition(getViewInformation2D()));
1261*b1cdbd2cSJim Jagielski                     }
1262*b1cdbd2cSJim Jagielski                 }
1263*b1cdbd2cSJim Jagielski             }
1264*b1cdbd2cSJim Jagielski         }
1265*b1cdbd2cSJim Jagielski 
RenderSvgLinearAtomPrimitive2D(const primitive2d::SvgLinearAtomPrimitive2D & rCandidate)1266*b1cdbd2cSJim Jagielski         void VclProcessor2D::RenderSvgLinearAtomPrimitive2D(const primitive2d::SvgLinearAtomPrimitive2D& rCandidate)
1267*b1cdbd2cSJim Jagielski         {
1268*b1cdbd2cSJim Jagielski             const double fDelta(rCandidate.getOffsetB() - rCandidate.getOffsetA());
1269*b1cdbd2cSJim Jagielski 
1270*b1cdbd2cSJim Jagielski             if(basegfx::fTools::more(fDelta, 0.0))
1271*b1cdbd2cSJim Jagielski             {
1272*b1cdbd2cSJim Jagielski                 const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
1273*b1cdbd2cSJim Jagielski                 const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB()));
1274*b1cdbd2cSJim Jagielski 
1275*b1cdbd2cSJim Jagielski                 // calculate discrete unit in WorldCoordinates; use diagonal (1.0, 1.0) and divide by sqrt(2)
1276*b1cdbd2cSJim Jagielski                 const basegfx::B2DVector aDiscreteVector(getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
1277*b1cdbd2cSJim Jagielski                 const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373));
1278*b1cdbd2cSJim Jagielski 
1279*b1cdbd2cSJim Jagielski                 // use color distance and discrete lengths to calculate step count
1280*b1cdbd2cSJim Jagielski                 const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDelta, fDiscreteUnit));
1281*b1cdbd2cSJim Jagielski 
1282*b1cdbd2cSJim Jagielski                 // switch off line painting
1283*b1cdbd2cSJim Jagielski                 mpOutputDevice->SetLineColor();
1284*b1cdbd2cSJim Jagielski 
1285*b1cdbd2cSJim Jagielski                 // prepare polygon in needed width at start position (with discrete overlap)
1286*b1cdbd2cSJim Jagielski                 const basegfx::B2DPolygon aPolygon(
1287*b1cdbd2cSJim Jagielski                     basegfx::tools::createPolygonFromRect(
1288*b1cdbd2cSJim Jagielski                         basegfx::B2DRange(
1289*b1cdbd2cSJim Jagielski                             rCandidate.getOffsetA() - fDiscreteUnit,
1290*b1cdbd2cSJim Jagielski                             0.0,
1291*b1cdbd2cSJim Jagielski                             rCandidate.getOffsetA() + (fDelta / nSteps) + fDiscreteUnit,
1292*b1cdbd2cSJim Jagielski                             1.0)));
1293*b1cdbd2cSJim Jagielski 
1294*b1cdbd2cSJim Jagielski 
1295*b1cdbd2cSJim Jagielski                 // prepare loop ([0.0 .. 1.0[)
1296*b1cdbd2cSJim Jagielski                 double fUnitScale(0.0);
1297*b1cdbd2cSJim Jagielski                 const double fUnitStep(1.0 / nSteps);
1298*b1cdbd2cSJim Jagielski 
1299*b1cdbd2cSJim Jagielski                 // loop and paint
1300*b1cdbd2cSJim Jagielski                 for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep)
1301*b1cdbd2cSJim Jagielski                 {
1302*b1cdbd2cSJim Jagielski                     basegfx::B2DPolygon aNew(aPolygon);
1303*b1cdbd2cSJim Jagielski 
1304*b1cdbd2cSJim Jagielski                     aNew.transform(maCurrentTransformation * basegfx::tools::createTranslateB2DHomMatrix(fDelta * fUnitScale, 0.0));
1305*b1cdbd2cSJim Jagielski                     mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorA, aColorB, fUnitScale)));
1306*b1cdbd2cSJim Jagielski                     mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew));
1307*b1cdbd2cSJim Jagielski                 }
1308*b1cdbd2cSJim Jagielski             }
1309*b1cdbd2cSJim Jagielski         }
1310*b1cdbd2cSJim Jagielski 
RenderSvgRadialAtomPrimitive2D(const primitive2d::SvgRadialAtomPrimitive2D & rCandidate)1311*b1cdbd2cSJim Jagielski         void VclProcessor2D::RenderSvgRadialAtomPrimitive2D(const primitive2d::SvgRadialAtomPrimitive2D& rCandidate)
1312*b1cdbd2cSJim Jagielski         {
1313*b1cdbd2cSJim Jagielski             const double fDeltaScale(rCandidate.getScaleB() - rCandidate.getScaleA());
1314*b1cdbd2cSJim Jagielski 
1315*b1cdbd2cSJim Jagielski             if(basegfx::fTools::more(fDeltaScale, 0.0))
1316*b1cdbd2cSJim Jagielski             {
1317*b1cdbd2cSJim Jagielski                 const basegfx::BColor aColorA(maBColorModifierStack.getModifiedColor(rCandidate.getColorA()));
1318*b1cdbd2cSJim Jagielski                 const basegfx::BColor aColorB(maBColorModifierStack.getModifiedColor(rCandidate.getColorB()));
1319*b1cdbd2cSJim Jagielski 
1320*b1cdbd2cSJim Jagielski                 // calculate discrete unit in WorldCoordinates; use diagonal (1.0, 1.0) and divide by sqrt(2)
1321*b1cdbd2cSJim Jagielski                 const basegfx::B2DVector aDiscreteVector(getViewInformation2D().getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
1322*b1cdbd2cSJim Jagielski                 const double fDiscreteUnit(aDiscreteVector.getLength() * (1.0 / 1.414213562373));
1323*b1cdbd2cSJim Jagielski 
1324*b1cdbd2cSJim Jagielski                 // use color distance and discrete lengths to calculate step count
1325*b1cdbd2cSJim Jagielski                 const sal_uInt32 nSteps(calculateStepsForSvgGradient(aColorA, aColorB, fDeltaScale, fDiscreteUnit));
1326*b1cdbd2cSJim Jagielski 
1327*b1cdbd2cSJim Jagielski                 // switch off line painting
1328*b1cdbd2cSJim Jagielski                 mpOutputDevice->SetLineColor();
1329*b1cdbd2cSJim Jagielski 
1330*b1cdbd2cSJim Jagielski                 // prepare loop ([0.0 .. 1.0[, full polygons, no polypolygons with holes)
1331*b1cdbd2cSJim Jagielski                 double fUnitScale(0.0);
1332*b1cdbd2cSJim Jagielski                 const double fUnitStep(1.0 / nSteps);
1333*b1cdbd2cSJim Jagielski 
1334*b1cdbd2cSJim Jagielski                 for(sal_uInt32 a(0); a < nSteps; a++, fUnitScale += fUnitStep)
1335*b1cdbd2cSJim Jagielski                 {
1336*b1cdbd2cSJim Jagielski                     basegfx::B2DHomMatrix aTransform;
1337*b1cdbd2cSJim Jagielski                     const double fEndScale(rCandidate.getScaleB() - (fDeltaScale * fUnitScale));
1338*b1cdbd2cSJim Jagielski 
1339*b1cdbd2cSJim Jagielski                     if(rCandidate.isTranslateSet())
1340*b1cdbd2cSJim Jagielski                     {
1341*b1cdbd2cSJim Jagielski                         const basegfx::B2DVector aTranslate(
1342*b1cdbd2cSJim Jagielski                             basegfx::interpolate(
1343*b1cdbd2cSJim Jagielski                                 rCandidate.getTranslateB(),
1344*b1cdbd2cSJim Jagielski                                 rCandidate.getTranslateA(),
1345*b1cdbd2cSJim Jagielski                                 fUnitScale));
1346*b1cdbd2cSJim Jagielski 
1347*b1cdbd2cSJim Jagielski                         aTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
1348*b1cdbd2cSJim Jagielski                             fEndScale,
1349*b1cdbd2cSJim Jagielski                             fEndScale,
1350*b1cdbd2cSJim Jagielski                             aTranslate.getX(),
1351*b1cdbd2cSJim Jagielski                             aTranslate.getY());
1352*b1cdbd2cSJim Jagielski                     }
1353*b1cdbd2cSJim Jagielski                     else
1354*b1cdbd2cSJim Jagielski                     {
1355*b1cdbd2cSJim Jagielski                         aTransform = basegfx::tools::createScaleB2DHomMatrix(
1356*b1cdbd2cSJim Jagielski                             fEndScale,
1357*b1cdbd2cSJim Jagielski                             fEndScale);
1358*b1cdbd2cSJim Jagielski                     }
1359*b1cdbd2cSJim Jagielski 
1360*b1cdbd2cSJim Jagielski                     basegfx::B2DPolygon aNew(basegfx::tools::createPolygonFromUnitCircle());
1361*b1cdbd2cSJim Jagielski 
1362*b1cdbd2cSJim Jagielski                     aNew.transform(maCurrentTransformation * aTransform);
1363*b1cdbd2cSJim Jagielski                     mpOutputDevice->SetFillColor(Color(basegfx::interpolate(aColorB, aColorA, fUnitScale)));
1364*b1cdbd2cSJim Jagielski                     mpOutputDevice->DrawPolyPolygon(basegfx::B2DPolyPolygon(aNew));
1365*b1cdbd2cSJim Jagielski                 }
1366*b1cdbd2cSJim Jagielski             }
1367*b1cdbd2cSJim Jagielski         }
1368*b1cdbd2cSJim Jagielski 
adaptLineToFillDrawMode() const1369*b1cdbd2cSJim Jagielski 		void VclProcessor2D::adaptLineToFillDrawMode() const
1370*b1cdbd2cSJim Jagielski 		{
1371*b1cdbd2cSJim Jagielski 			const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
1372*b1cdbd2cSJim Jagielski 
1373*b1cdbd2cSJim Jagielski 			if(nOriginalDrawMode & (DRAWMODE_BLACKLINE|DRAWMODE_GRAYLINE|DRAWMODE_GHOSTEDLINE|DRAWMODE_WHITELINE|DRAWMODE_SETTINGSLINE))
1374*b1cdbd2cSJim Jagielski 			{
1375*b1cdbd2cSJim Jagielski 				sal_uInt32 nAdaptedDrawMode(nOriginalDrawMode);
1376*b1cdbd2cSJim Jagielski 
1377*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_BLACKLINE)
1378*b1cdbd2cSJim Jagielski 				{
1379*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_BLACKFILL;
1380*b1cdbd2cSJim Jagielski 				}
1381*b1cdbd2cSJim Jagielski 				else
1382*b1cdbd2cSJim Jagielski 				{
1383*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL;
1384*b1cdbd2cSJim Jagielski 				}
1385*b1cdbd2cSJim Jagielski 
1386*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_GRAYLINE)
1387*b1cdbd2cSJim Jagielski 				{
1388*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_GRAYFILL;
1389*b1cdbd2cSJim Jagielski 				}
1390*b1cdbd2cSJim Jagielski 				else
1391*b1cdbd2cSJim Jagielski 				{
1392*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL;
1393*b1cdbd2cSJim Jagielski 				}
1394*b1cdbd2cSJim Jagielski 
1395*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_GHOSTEDLINE)
1396*b1cdbd2cSJim Jagielski 				{
1397*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL;
1398*b1cdbd2cSJim Jagielski 				}
1399*b1cdbd2cSJim Jagielski 				else
1400*b1cdbd2cSJim Jagielski 				{
1401*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL;
1402*b1cdbd2cSJim Jagielski 				}
1403*b1cdbd2cSJim Jagielski 
1404*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_WHITELINE)
1405*b1cdbd2cSJim Jagielski 				{
1406*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_WHITEFILL;
1407*b1cdbd2cSJim Jagielski 				}
1408*b1cdbd2cSJim Jagielski 				else
1409*b1cdbd2cSJim Jagielski 				{
1410*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL;
1411*b1cdbd2cSJim Jagielski 				}
1412*b1cdbd2cSJim Jagielski 
1413*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_SETTINGSLINE)
1414*b1cdbd2cSJim Jagielski 				{
1415*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL;
1416*b1cdbd2cSJim Jagielski 				}
1417*b1cdbd2cSJim Jagielski 				else
1418*b1cdbd2cSJim Jagielski 				{
1419*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL;
1420*b1cdbd2cSJim Jagielski 				}
1421*b1cdbd2cSJim Jagielski 
1422*b1cdbd2cSJim Jagielski 				mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
1423*b1cdbd2cSJim Jagielski 			}
1424*b1cdbd2cSJim Jagielski 		}
1425*b1cdbd2cSJim Jagielski 
adaptTextToFillDrawMode() const1426*b1cdbd2cSJim Jagielski 		void VclProcessor2D::adaptTextToFillDrawMode() const
1427*b1cdbd2cSJim Jagielski 		{
1428*b1cdbd2cSJim Jagielski 			const sal_uInt32 nOriginalDrawMode(mpOutputDevice->GetDrawMode());
1429*b1cdbd2cSJim Jagielski 			if(nOriginalDrawMode & (DRAWMODE_BLACKTEXT|DRAWMODE_GRAYTEXT|DRAWMODE_GHOSTEDTEXT|DRAWMODE_WHITETEXT|DRAWMODE_SETTINGSTEXT))
1430*b1cdbd2cSJim Jagielski 			{
1431*b1cdbd2cSJim Jagielski 				sal_uInt32 nAdaptedDrawMode(nOriginalDrawMode);
1432*b1cdbd2cSJim Jagielski 
1433*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_BLACKTEXT)
1434*b1cdbd2cSJim Jagielski 				{
1435*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_BLACKFILL;
1436*b1cdbd2cSJim Jagielski 				}
1437*b1cdbd2cSJim Jagielski 				else
1438*b1cdbd2cSJim Jagielski 				{
1439*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_BLACKFILL;
1440*b1cdbd2cSJim Jagielski 				}
1441*b1cdbd2cSJim Jagielski 
1442*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_GRAYTEXT)
1443*b1cdbd2cSJim Jagielski 				{
1444*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_GRAYFILL;
1445*b1cdbd2cSJim Jagielski 				}
1446*b1cdbd2cSJim Jagielski 				else
1447*b1cdbd2cSJim Jagielski 				{
1448*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_GRAYFILL;
1449*b1cdbd2cSJim Jagielski 				}
1450*b1cdbd2cSJim Jagielski 
1451*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_GHOSTEDTEXT)
1452*b1cdbd2cSJim Jagielski 				{
1453*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_GHOSTEDFILL;
1454*b1cdbd2cSJim Jagielski 				}
1455*b1cdbd2cSJim Jagielski 				else
1456*b1cdbd2cSJim Jagielski 				{
1457*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_GHOSTEDFILL;
1458*b1cdbd2cSJim Jagielski 				}
1459*b1cdbd2cSJim Jagielski 
1460*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_WHITETEXT)
1461*b1cdbd2cSJim Jagielski 				{
1462*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_WHITEFILL;
1463*b1cdbd2cSJim Jagielski 				}
1464*b1cdbd2cSJim Jagielski 				else
1465*b1cdbd2cSJim Jagielski 				{
1466*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_WHITEFILL;
1467*b1cdbd2cSJim Jagielski 				}
1468*b1cdbd2cSJim Jagielski 
1469*b1cdbd2cSJim Jagielski 				if(nOriginalDrawMode & DRAWMODE_SETTINGSTEXT)
1470*b1cdbd2cSJim Jagielski 				{
1471*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode |= DRAWMODE_SETTINGSFILL;
1472*b1cdbd2cSJim Jagielski 				}
1473*b1cdbd2cSJim Jagielski 				else
1474*b1cdbd2cSJim Jagielski 				{
1475*b1cdbd2cSJim Jagielski 					nAdaptedDrawMode &= ~DRAWMODE_SETTINGSFILL;
1476*b1cdbd2cSJim Jagielski 				}
1477*b1cdbd2cSJim Jagielski 
1478*b1cdbd2cSJim Jagielski 				mpOutputDevice->SetDrawMode(nAdaptedDrawMode);
1479*b1cdbd2cSJim Jagielski 			}
1480*b1cdbd2cSJim Jagielski 		}
1481*b1cdbd2cSJim Jagielski 
1482*b1cdbd2cSJim Jagielski 		//////////////////////////////////////////////////////////////////////////////
1483*b1cdbd2cSJim Jagielski 		// process support
1484*b1cdbd2cSJim Jagielski 
VclProcessor2D(const geometry::ViewInformation2D & rViewInformation,OutputDevice & rOutDev)1485*b1cdbd2cSJim Jagielski 		VclProcessor2D::VclProcessor2D(
1486*b1cdbd2cSJim Jagielski 			const geometry::ViewInformation2D& rViewInformation,
1487*b1cdbd2cSJim Jagielski 			OutputDevice& rOutDev)
1488*b1cdbd2cSJim Jagielski 		:	BaseProcessor2D(rViewInformation),
1489*b1cdbd2cSJim Jagielski 			mpOutputDevice(&rOutDev),
1490*b1cdbd2cSJim Jagielski 			maBColorModifierStack(),
1491*b1cdbd2cSJim Jagielski 			maCurrentTransformation(),
1492*b1cdbd2cSJim Jagielski 			maDrawinglayerOpt(),
1493*b1cdbd2cSJim Jagielski             mnPolygonStrokePrimitive2D(0)
1494*b1cdbd2cSJim Jagielski 		{
1495*b1cdbd2cSJim Jagielski             // set digit language, derived from SvtCTLOptions to have the correct
1496*b1cdbd2cSJim Jagielski             // number display for arabic/hindi numerals
1497*b1cdbd2cSJim Jagielski             const SvtCTLOptions aSvtCTLOptions;
1498*b1cdbd2cSJim Jagielski             LanguageType eLang(LANGUAGE_SYSTEM);
1499*b1cdbd2cSJim Jagielski 
1500*b1cdbd2cSJim Jagielski             if(SvtCTLOptions::NUMERALS_HINDI == aSvtCTLOptions.GetCTLTextNumerals())
1501*b1cdbd2cSJim Jagielski             {
1502*b1cdbd2cSJim Jagielski                 eLang = LANGUAGE_ARABIC_SAUDI_ARABIA;
1503*b1cdbd2cSJim Jagielski             }
1504*b1cdbd2cSJim Jagielski             else if(SvtCTLOptions::NUMERALS_ARABIC == aSvtCTLOptions.GetCTLTextNumerals())
1505*b1cdbd2cSJim Jagielski             {
1506*b1cdbd2cSJim Jagielski                 eLang = LANGUAGE_ENGLISH;
1507*b1cdbd2cSJim Jagielski             }
1508*b1cdbd2cSJim Jagielski             else
1509*b1cdbd2cSJim Jagielski             {
1510*b1cdbd2cSJim Jagielski                 eLang = (LanguageType)Application::GetSettings().GetLanguage();
1511*b1cdbd2cSJim Jagielski             }
1512*b1cdbd2cSJim Jagielski 
1513*b1cdbd2cSJim Jagielski             rOutDev.SetDigitLanguage(eLang);
1514*b1cdbd2cSJim Jagielski 		}
1515*b1cdbd2cSJim Jagielski 
~VclProcessor2D()1516*b1cdbd2cSJim Jagielski 		VclProcessor2D::~VclProcessor2D()
1517*b1cdbd2cSJim Jagielski 		{
1518*b1cdbd2cSJim Jagielski 		}
1519*b1cdbd2cSJim Jagielski 	} // end of namespace processor2d
1520*b1cdbd2cSJim Jagielski } // end of namespace drawinglayer
1521*b1cdbd2cSJim Jagielski 
1522*b1cdbd2cSJim Jagielski //////////////////////////////////////////////////////////////////////////////
1523*b1cdbd2cSJim Jagielski // eof
1524