Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <tools/debug.hxx>
31 : : #include <tools/line.hxx>
32 : : #include <tools/poly.hxx>
33 : :
34 : : #include <vcl/gradient.hxx>
35 : : #include <vcl/metaact.hxx>
36 : : #include <vcl/gdimtf.hxx>
37 : : #include <vcl/salbtype.hxx>
38 : : #include <vcl/hatch.hxx>
39 : : #include <vcl/window.hxx>
40 : : #include <vcl/virdev.hxx>
41 : : #include <vcl/outdev.hxx>
42 : :
43 : : #include "pdfwriter_impl.hxx"
44 : :
45 : : #include "window.h"
46 : : #include "salframe.hxx"
47 : : #include "salgdi.hxx"
48 : : #include "svdata.hxx"
49 : : #include "outdata.hxx"
50 : :
51 : : #include <basegfx/polygon/b2dpolygon.hxx>
52 : : #include <basegfx/polygon/b2dpolypolygon.hxx>
53 : : #include <basegfx/matrix/b2dhommatrix.hxx>
54 : :
55 : : // -----------
56 : : // - Defines -
57 : : // -----------
58 : :
59 : : #define HATCH_MAXPOINTS 1024
60 : : #define GRADIENT_DEFAULT_STEPCOUNT 0
61 : :
62 : : // ----------------
63 : : // - Cmp-Function -
64 : : // ----------------
65 : :
66 : 31724 : extern "C" int __LOADONCALLAPI ImplHatchCmpFnc( const void* p1, const void* p2 )
67 : : {
68 : 31724 : const long nX1 = ( (Point*) p1 )->X();
69 : 31724 : const long nX2 = ( (Point*) p2 )->X();
70 : 31724 : const long nY1 = ( (Point*) p1 )->Y();
71 : 31724 : const long nY2 = ( (Point*) p2 )->Y();
72 : :
73 [ # # ][ # # ]: 31724 : return ( nX1 > nX2 ? 1 : nX1 == nX2 ? nY1 > nY2 ? 1: nY1 == nY2 ? 0 : -1 : -1 );
[ # # ][ - + ]
74 : : }
75 : :
76 : : // =======================================================================
77 : :
78 : : DBG_NAMEEX( OutputDevice )
79 : : DBG_NAMEEX( Gradient )
80 : :
81 : : // =======================================================================
82 : :
83 : 2321362 : void OutputDevice::ImplDrawPolygon( const Polygon& rPoly, const PolyPolygon* pClipPolyPoly )
84 : : {
85 [ - + ]: 2321362 : if( pClipPolyPoly )
86 [ # # ]: 0 : ImplDrawPolyPolygon( rPoly, pClipPolyPoly );
87 : : else
88 : : {
89 : 2321362 : sal_uInt16 nPoints = rPoly.GetSize();
90 : :
91 [ - + ]: 2321362 : if ( nPoints < 2 )
92 : 2321362 : return;
93 : :
94 : 2321362 : const SalPoint* pPtAry = (const SalPoint*)rPoly.GetConstPointAry();
95 : 2321362 : mpGraphics->DrawPolygon( nPoints, pPtAry, this );
96 : : }
97 : : }
98 : :
99 : : // -----------------------------------------------------------------------
100 : :
101 : 0 : void OutputDevice::ImplDrawPolyPolygon( const PolyPolygon& rPolyPoly, const PolyPolygon* pClipPolyPoly )
102 : : {
103 : : PolyPolygon* pPolyPoly;
104 : :
105 [ # # ]: 0 : if( pClipPolyPoly )
106 : : {
107 [ # # ]: 0 : pPolyPoly = new PolyPolygon;
108 : 0 : rPolyPoly.GetIntersection( *pClipPolyPoly, *pPolyPoly );
109 : : }
110 : : else
111 : 0 : pPolyPoly = (PolyPolygon*) &rPolyPoly;
112 : :
113 [ # # ]: 0 : if( pPolyPoly->Count() == 1 )
114 : : {
115 [ # # ][ # # ]: 0 : const Polygon rPoly = pPolyPoly->GetObject( 0 );
116 [ # # ]: 0 : sal_uInt16 nSize = rPoly.GetSize();
117 : :
118 [ # # ]: 0 : if( nSize >= 2 )
119 : : {
120 [ # # ]: 0 : const SalPoint* pPtAry = (const SalPoint*)rPoly.GetConstPointAry();
121 [ # # ]: 0 : mpGraphics->DrawPolygon( nSize, pPtAry, this );
122 [ # # ]: 0 : }
123 : : }
124 [ # # ]: 0 : else if( pPolyPoly->Count() )
125 : : {
126 : 0 : sal_uInt16 nCount = pPolyPoly->Count();
127 : 0 : sal_uInt32* pPointAry = new sal_uInt32[nCount];
128 : 0 : PCONSTSALPOINT* pPointAryAry = new PCONSTSALPOINT[nCount];
129 : 0 : sal_uInt16 i = 0;
130 [ # # ]: 0 : do
131 : : {
132 : 0 : const Polygon& rPoly = pPolyPoly->GetObject( i );
133 : 0 : sal_uInt16 nSize = rPoly.GetSize();
134 [ # # ]: 0 : if ( nSize )
135 : : {
136 : 0 : pPointAry[i] = nSize;
137 : 0 : pPointAryAry[i] = (PCONSTSALPOINT)rPoly.GetConstPointAry();
138 : 0 : i++;
139 : : }
140 : : else
141 : 0 : nCount--;
142 : : }
143 : : while( i < nCount );
144 : :
145 [ # # ]: 0 : if( nCount == 1 )
146 : 0 : mpGraphics->DrawPolygon( *pPointAry, *pPointAryAry, this );
147 : : else
148 : 0 : mpGraphics->DrawPolyPolygon( nCount, pPointAry, pPointAryAry, this );
149 : :
150 [ # # ]: 0 : delete[] pPointAry;
151 [ # # ]: 0 : delete[] pPointAryAry;
152 : : }
153 : :
154 [ # # ]: 0 : if( pClipPolyPoly )
155 [ # # ]: 0 : delete pPolyPoly;
156 : 0 : }
157 : :
158 : : // -----------------------------------------------------------------------
159 : :
160 : 6922431 : inline sal_uInt8 ImplGetGradientColorValue( long nValue )
161 : : {
162 [ - + ]: 6922431 : if ( nValue < 0 )
163 : 0 : return 0;
164 [ - + ]: 6922431 : else if ( nValue > 0xFF )
165 : 0 : return 0xFF;
166 : : else
167 : 6922431 : return (sal_uInt8)nValue;
168 : : }
169 : :
170 : : // -----------------------------------------------------------------------
171 : :
172 : 112334 : void OutputDevice::ImplDrawLinearGradient( const Rectangle& rRect,
173 : : const Gradient& rGradient,
174 : : sal_Bool bMtf, const PolyPolygon* pClipPolyPoly )
175 : : {
176 : : // rotiertes BoundRect ausrechnen
177 [ + - ]: 112334 : Rectangle aRect;
178 : 112334 : Point aCenter;
179 : 112334 : sal_uInt16 nAngle = rGradient.GetAngle() % 3600;
180 : :
181 [ + - ]: 112334 : rGradient.GetBoundRect( rRect, aRect, aCenter );
182 : :
183 : : // Rand berechnen und Rechteck neu setzen
184 : 112334 : Rectangle aFullRect = aRect;
185 [ + - ]: 112334 : long nBorder = (long)rGradient.GetBorder() * aRect.GetHeight() / 100;
186 : :
187 : : // Rand berechnen und Rechteck neu setzen fuer linearen Farbverlauf
188 : 112334 : bool bLinear = (rGradient.GetStyle() == GradientStyle_LINEAR);
189 [ + - ]: 112334 : if ( bLinear )
190 : : {
191 : 112334 : aRect.Top() += nBorder;
192 : : }
193 : : // Rand berechnen und Rechteck neu setzen fuer axiale Farbverlauf
194 : : else
195 : : {
196 : 0 : nBorder >>= 1;
197 : :
198 : 0 : aRect.Top() += nBorder;
199 : 0 : aRect.Bottom() -= nBorder;
200 : : }
201 : :
202 : : // Top darf nicht groesser als Bottom sein
203 : 112334 : aRect.Top() = Min( aRect.Top(), (long)(aRect.Bottom() - 1) );
204 : :
205 [ + - ]: 112334 : long nMinRect = aRect.GetHeight();
206 : :
207 : : // Intensitaeten von Start- und Endfarbe ggf. aendern und
208 : : // Farbschrittweiten berechnen
209 : : long nFactor;
210 : 112334 : Color aStartCol = rGradient.GetStartColor();
211 : 112334 : Color aEndCol = rGradient.GetEndColor();
212 : 112334 : long nStartRed = aStartCol.GetRed();
213 : 112334 : long nStartGreen = aStartCol.GetGreen();
214 : 112334 : long nStartBlue = aStartCol.GetBlue();
215 : 112334 : long nEndRed = aEndCol.GetRed();
216 : 112334 : long nEndGreen = aEndCol.GetGreen();
217 : 112334 : long nEndBlue = aEndCol.GetBlue();
218 : 112334 : nFactor = rGradient.GetStartIntensity();
219 : 112334 : nStartRed = (nStartRed * nFactor) / 100;
220 : 112334 : nStartGreen = (nStartGreen * nFactor) / 100;
221 : 112334 : nStartBlue = (nStartBlue * nFactor) / 100;
222 : 112334 : nFactor = rGradient.GetEndIntensity();
223 : 112334 : nEndRed = (nEndRed * nFactor) / 100;
224 : 112334 : nEndGreen = (nEndGreen * nFactor) / 100;
225 : 112334 : nEndBlue = (nEndBlue * nFactor) / 100;
226 : 112334 : long nRedSteps = nEndRed - nStartRed;
227 : 112334 : long nGreenSteps = nEndGreen - nStartGreen;
228 : 112334 : long nBlueSteps = nEndBlue - nStartBlue;
229 : 112334 : long nStepCount = rGradient.GetSteps();
230 : :
231 : : // Bei nicht linearen Farbverlaeufen haben wir nur die halben Steps
232 : : // pro Farbe
233 [ - + ]: 112334 : if ( !bLinear )
234 : : {
235 : 0 : nRedSteps <<= 1;
236 : 0 : nGreenSteps <<= 1;
237 : 0 : nBlueSteps <<= 1;
238 : : }
239 : :
240 : : // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
241 [ + - ]: 112334 : if ( !nStepCount )
242 : : {
243 : : long nInc;
244 : :
245 [ + - ][ + - ]: 112334 : if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
246 : : {
247 [ + + ]: 112334 : nInc = (nMinRect < 50) ? 2 : 4;
248 : : }
249 : : else
250 : : {
251 : : // #105998# Use display-equivalent step size calculation
252 [ # # ]: 0 : nInc = (nMinRect < 800) ? 10 : 20;
253 : : }
254 : :
255 [ - + ]: 112334 : if ( !nInc )
256 : 0 : nInc = 1;
257 : :
258 : 112334 : nStepCount = nMinRect / nInc;
259 : : }
260 : : // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
261 : 112334 : long nSteps = Max( nStepCount, 2L );
262 : 112334 : long nCalcSteps = Abs( nRedSteps );
263 : 112334 : long nTempSteps = Abs( nGreenSteps );
264 [ - + ]: 112334 : if ( nTempSteps > nCalcSteps )
265 : 0 : nCalcSteps = nTempSteps;
266 : 112334 : nTempSteps = Abs( nBlueSteps );
267 [ - + ]: 112334 : if ( nTempSteps > nCalcSteps )
268 : 0 : nCalcSteps = nTempSteps;
269 [ + + ]: 112334 : if ( nCalcSteps < nSteps )
270 : 4501 : nSteps = nCalcSteps;
271 [ + + ]: 112334 : if ( !nSteps )
272 : 43 : nSteps = 1;
273 : :
274 : : // Falls axialer Farbverlauf, muss die Schrittanzahl ungerade sein
275 [ - + ][ # # ]: 112334 : if ( !bLinear && !(nSteps & 1) )
276 : 0 : nSteps++;
277 : :
278 : : // Berechnung ueber Double-Addition wegen Genauigkeit
279 : 112334 : double fScanLine = aRect.Top();
280 [ + - ]: 112334 : double fScanInc = (double)aRect.GetHeight() / (double)nSteps;
281 : :
282 : : // Startfarbe berechnen und setzen
283 : : sal_uInt8 nRed;
284 : : sal_uInt8 nGreen;
285 : : sal_uInt8 nBlue;
286 : : long nSteps2;
287 : 112334 : long nStepsHalf = 0;
288 [ + - ]: 112334 : if ( bLinear )
289 : : {
290 : : // Um 1 erhoeht, um die Border innerhalb der Schleife
291 : : // zeichnen zu koennen
292 : 112334 : nSteps2 = nSteps + 1;
293 : 112334 : nRed = (sal_uInt8)nStartRed;
294 : 112334 : nGreen = (sal_uInt8)nStartGreen;
295 : 112334 : nBlue = (sal_uInt8)nStartBlue;
296 : : }
297 : : else
298 : : {
299 : : // Um 2 erhoeht, um die Border innerhalb der Schleife
300 : : // zeichnen zu koennen
301 : 0 : nSteps2 = nSteps + 2;
302 : 0 : nRed = (sal_uInt8)nEndRed;
303 : 0 : nGreen = (sal_uInt8)nEndGreen;
304 : 0 : nBlue = (sal_uInt8)nEndBlue;
305 : 0 : nStepsHalf = nSteps >> 1;
306 : : }
307 : :
308 [ - + ]: 112334 : if ( bMtf )
309 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), sal_True ) );
[ # # ]
310 : : else
311 [ + - ]: 112334 : mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
312 : :
313 : : // Startpolygon erzeugen (== Borderpolygon)
314 [ + - ]: 112334 : Polygon aPoly( 4 );
315 [ + - ]: 112334 : Polygon aTempPoly( 2 );
316 [ + - ]: 112334 : Polygon aTempPoly2( 2 );
317 : : /* n#710061 Use overlapping fills to avoid color
318 : : * leak via gaps in some pdf viewers
319 : : */
320 : 112334 : Point aOverLap( 0, fScanInc*.1 );
321 [ + - ]: 112334 : aPoly[0] = aFullRect.TopLeft();
322 [ + - ][ + - ]: 112334 : aPoly[1] = aFullRect.TopRight();
323 [ + - ][ + - ]: 112334 : aPoly[2] = aRect.TopRight();
324 [ + - ]: 112334 : aPoly[3] = aRect.TopLeft();
325 [ + - ]: 112334 : aPoly.Rotate( aCenter, nAngle );
326 [ + - ][ + - ]: 112334 : aTempPoly[0] = aPoly[3];
327 [ + - ][ + - ]: 112334 : aTempPoly[1] = aPoly[2];
328 : :
329 : :
330 : : // Schleife, um rotierten Verlauf zu fuellen
331 [ + + ]: 2419811 : for ( long i = 0; i < nSteps2; i++ )
332 : : {
333 : : // berechnetesPolygon ausgeben
334 [ - + ]: 2307477 : if ( bMtf )
335 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
[ # # ]
336 : : else
337 [ + - ]: 2307477 : ImplDrawPolygon( aPoly, pClipPolyPoly );
338 : :
339 : : // neues Polygon berechnen
340 : 2307477 : aRect.Top() = (long)(fScanLine += fScanInc);
341 : :
342 [ + - ][ + - ]: 2307477 : aPoly[0] = aTempPoly[0];
343 [ + - ][ + - ]: 2307477 : aPoly[1] = aTempPoly[1];
344 : : // unteren Rand komplett fuellen
345 [ + + ]: 2307477 : if ( i == nSteps )
346 : : {
347 [ + - ][ + - ]: 112334 : aTempPoly[0] = aFullRect.BottomLeft();
348 [ + - ][ + - ]: 112334 : aTempPoly[1] = aFullRect.BottomRight();
349 [ + - ]: 112334 : aTempPoly2 = aTempPoly;
350 : : }
351 : : else
352 : : {
353 [ + - ]: 2195143 : aTempPoly[0] = aRect.TopLeft();
354 [ + - ][ + - ]: 2195143 : aTempPoly[1] = aRect.TopRight();
355 [ + - ][ + - ]: 2195143 : aTempPoly2[0]= aTempPoly[0] + aOverLap;
356 [ + - ][ + - ]: 2195143 : aTempPoly2[1]= aTempPoly[1] + aOverLap;
357 : : }
358 [ + - ]: 2307477 : aTempPoly2.Rotate( aCenter, nAngle );
359 [ + - ]: 2307477 : aTempPoly.Rotate( aCenter, nAngle );
360 : :
361 [ + - ][ + - ]: 2307477 : aPoly[2] = aTempPoly2[1];
362 [ + - ][ + - ]: 2307477 : aPoly[3] = aTempPoly2[0];
363 : :
364 : : // Farbintensitaeten aendern...
365 : : // fuer lineare FV
366 [ + - ]: 2307477 : if ( bLinear )
367 : : {
368 : 2307477 : nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i)/nSteps2) );
369 : 2307477 : nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i)/nSteps2) );
370 : 2307477 : nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i)/nSteps2) );
371 : : }
372 : : // fuer radiale FV
373 : : else
374 : : {
375 : : // fuer axiale FV muss die letzte Farbe der ersten
376 : : // Farbe entsprechen
377 : : // #107350# Setting end color one step earlier, as the
378 : : // last time we get here, we drop out of the loop later
379 : : // on.
380 [ # # ]: 0 : if ( i >= nSteps )
381 : : {
382 : 0 : nRed = (sal_uInt8)nEndRed;
383 : 0 : nGreen = (sal_uInt8)nEndGreen;
384 : 0 : nBlue = (sal_uInt8)nEndBlue;
385 : : }
386 : : else
387 : : {
388 [ # # ]: 0 : if ( i <= nStepsHalf )
389 : : {
390 : 0 : nRed = ImplGetGradientColorValue( nEndRed-((nRedSteps*i)/nSteps2) );
391 : 0 : nGreen = ImplGetGradientColorValue( nEndGreen-((nGreenSteps*i)/nSteps2) );
392 : 0 : nBlue = ImplGetGradientColorValue( nEndBlue-((nBlueSteps*i)/nSteps2) );
393 : : }
394 : : // genau die Mitte und hoeher
395 : : else
396 : : {
397 : 0 : long i2 = i - nStepsHalf;
398 : 0 : nRed = ImplGetGradientColorValue( nStartRed+((nRedSteps*i2)/nSteps2) );
399 : 0 : nGreen = ImplGetGradientColorValue( nStartGreen+((nGreenSteps*i2)/nSteps2) );
400 : 0 : nBlue = ImplGetGradientColorValue( nStartBlue+((nBlueSteps*i2)/nSteps2) );
401 : : }
402 : : }
403 : : }
404 : :
405 [ - + ]: 2307477 : if ( bMtf )
406 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), sal_True ) );
[ # # ]
407 : : else
408 [ + - ]: 2307477 : mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
409 [ + - ][ + - ]: 112334 : }
[ + - ]
410 : 112334 : }
411 : :
412 : : // -----------------------------------------------------------------------
413 : :
414 : 0 : void OutputDevice::ImplDrawComplexGradient( const Rectangle& rRect,
415 : : const Gradient& rGradient,
416 : : sal_Bool bMtf, const PolyPolygon* pClipPolyPoly )
417 : : {
418 : : // Feststellen ob Ausgabe ueber Polygon oder PolyPolygon
419 : : // Bei Rasteroperationen ungleich Overpaint immer PolyPolygone,
420 : : // da es zu falschen Ergebnissen kommt, wenn man mehrfach uebereinander
421 : : // ausgibt
422 : : // Bei Druckern auch immer PolyPolygone, da nicht alle Drucker
423 : : // das Uebereinanderdrucken von Polygonen koennen
424 : : // Virtuelle Device werden auch ausgeklammert, da einige Treiber
425 : : // ansonsten zu langsam sind
426 : : PolyPolygon* pPolyPoly;
427 [ # # ]: 0 : Rectangle aRect;
428 : 0 : Point aCenter;
429 : 0 : Color aStartCol( rGradient.GetStartColor() );
430 : 0 : Color aEndCol( rGradient.GetEndColor() );
431 : 0 : long nStartRed = ( (long) aStartCol.GetRed() * rGradient.GetStartIntensity() ) / 100;
432 : 0 : long nStartGreen = ( (long) aStartCol.GetGreen() * rGradient.GetStartIntensity() ) / 100;
433 : 0 : long nStartBlue = ( (long) aStartCol.GetBlue() * rGradient.GetStartIntensity() ) / 100;
434 : 0 : long nEndRed = ( (long) aEndCol.GetRed() * rGradient.GetEndIntensity() ) / 100;
435 : 0 : long nEndGreen = ( (long) aEndCol.GetGreen() * rGradient.GetEndIntensity() ) / 100;
436 : 0 : long nEndBlue = ( (long) aEndCol.GetBlue() * rGradient.GetEndIntensity() ) / 100;
437 : 0 : long nRedSteps = nEndRed - nStartRed;
438 : 0 : long nGreenSteps = nEndGreen - nStartGreen;
439 : 0 : long nBlueSteps = nEndBlue - nStartBlue;
440 : 0 : long nStepCount = rGradient.GetSteps();
441 : 0 : sal_uInt16 nAngle = rGradient.GetAngle() % 3600;
442 : :
443 [ # # ]: 0 : rGradient.GetBoundRect( rRect, aRect, aCenter );
444 : :
445 [ # # ][ # # ]: 0 : if( (meRasterOp != ROP_OVERPAINT) || (meOutDevType != OUTDEV_WINDOW) || bMtf )
[ # # ]
446 [ # # ][ # # ]: 0 : pPolyPoly = new PolyPolygon( 2 );
447 : : else
448 : 0 : pPolyPoly = NULL;
449 : :
450 [ # # ][ # # ]: 0 : long nMinRect = Min( aRect.GetWidth(), aRect.GetHeight() );
451 : :
452 : : // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
453 [ # # ]: 0 : if( !nStepCount )
454 : : {
455 : : long nInc;
456 : :
457 [ # # ][ # # ]: 0 : if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
458 : : {
459 [ # # ]: 0 : nInc = ( nMinRect < 50 ) ? 2 : 4;
460 : : }
461 : : else
462 : : {
463 : : // #105998# Use display-equivalent step size calculation
464 [ # # ]: 0 : nInc = (nMinRect < 800) ? 10 : 20;
465 : : }
466 : :
467 [ # # ]: 0 : if( !nInc )
468 : 0 : nInc = 1;
469 : :
470 : 0 : nStepCount = nMinRect / nInc;
471 : : }
472 : :
473 : : // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
474 : 0 : long nSteps = Max( nStepCount, 2L );
475 : 0 : long nCalcSteps = Abs( nRedSteps );
476 : 0 : long nTempSteps = Abs( nGreenSteps );
477 [ # # ]: 0 : if ( nTempSteps > nCalcSteps )
478 : 0 : nCalcSteps = nTempSteps;
479 : 0 : nTempSteps = Abs( nBlueSteps );
480 [ # # ]: 0 : if ( nTempSteps > nCalcSteps )
481 : 0 : nCalcSteps = nTempSteps;
482 [ # # ]: 0 : if ( nCalcSteps < nSteps )
483 : 0 : nSteps = nCalcSteps;
484 [ # # ]: 0 : if ( !nSteps )
485 : 0 : nSteps = 1;
486 : :
487 : : // Ausgabebegrenzungen und Schrittweite fuer jede Richtung festlegen
488 [ # # ]: 0 : Polygon aPoly;
489 : 0 : double fScanLeft = aRect.Left();
490 : 0 : double fScanTop = aRect.Top();
491 : 0 : double fScanRight = aRect.Right();
492 : 0 : double fScanBottom = aRect.Bottom();
493 : 0 : double fScanInc = (double) nMinRect / (double) nSteps * 0.5;
494 : 0 : sal_uInt8 nRed = (sal_uInt8) nStartRed, nGreen = (sal_uInt8) nStartGreen, nBlue = (sal_uInt8) nStartBlue;
495 : 0 : bool bPaintLastPolygon( false ); // #107349# Paint last polygon only if loop has generated any output
496 : :
497 [ # # ]: 0 : if( bMtf )
498 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), sal_True ) );
[ # # ]
499 : : else
500 [ # # ]: 0 : mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
501 : :
502 [ # # ]: 0 : if( pPolyPoly )
503 : : {
504 [ # # ][ # # ]: 0 : pPolyPoly->Insert( aPoly = rRect );
[ # # ][ # # ]
505 [ # # ]: 0 : pPolyPoly->Insert( aPoly );
506 : : }
507 : : else
508 : : {
509 : : // extend rect, to avoid missing bounding line
510 : 0 : Rectangle aExtRect( rRect );
511 : :
512 : 0 : aExtRect.Left() -= 1;
513 : 0 : aExtRect.Top() -= 1;
514 : 0 : aExtRect.Right() += 1;
515 : 0 : aExtRect.Bottom() += 1;
516 : :
517 [ # # ][ # # ]: 0 : ImplDrawPolygon( aPoly = aExtRect, pClipPolyPoly );
[ # # ][ # # ]
518 : : }
519 : :
520 : : // Schleife, um nacheinander die Polygone/PolyPolygone auszugeben
521 [ # # ]: 0 : for( long i = 1; i < nSteps; i++ )
522 : : {
523 : : // neues Polygon berechnen
524 : 0 : aRect.Left() = (long)( fScanLeft += fScanInc );
525 : 0 : aRect.Top() = (long)( fScanTop += fScanInc );
526 : 0 : aRect.Right() = (long)( fScanRight -= fScanInc );
527 : 0 : aRect.Bottom() = (long)( fScanBottom -= fScanInc );
528 : :
529 [ # # ][ # # ]: 0 : if( ( aRect.GetWidth() < 2 ) || ( aRect.GetHeight() < 2 ) )
[ # # ][ # # ]
[ # # ]
530 : 0 : break;
531 : :
532 [ # # ][ # # ]: 0 : if( rGradient.GetStyle() == GradientStyle_RADIAL || rGradient.GetStyle() == GradientStyle_ELLIPTICAL )
[ # # ]
533 [ # # ][ # # ]: 0 : aPoly = Polygon( aRect.Center(), aRect.GetWidth() >> 1, aRect.GetHeight() >> 1 );
[ # # ][ # # ]
[ # # ][ # # ]
534 : : else
535 [ # # ][ # # ]: 0 : aPoly = Polygon( aRect );
[ # # ]
536 : :
537 [ # # ]: 0 : aPoly.Rotate( aCenter, nAngle );
538 : :
539 : : // Farbe entsprechend anpassen
540 [ # # ]: 0 : const long nStepIndex = ( ( pPolyPoly != NULL ) ? i : ( i + 1 ) );
541 : 0 : nRed = ImplGetGradientColorValue( nStartRed + ( ( nRedSteps * nStepIndex ) / nSteps ) );
542 : 0 : nGreen = ImplGetGradientColorValue( nStartGreen + ( ( nGreenSteps * nStepIndex ) / nSteps ) );
543 : 0 : nBlue = ImplGetGradientColorValue( nStartBlue + ( ( nBlueSteps * nStepIndex ) / nSteps ) );
544 : :
545 : : // entweder langsame PolyPolygon-Ausgaben oder schnelles Polygon-Painting
546 [ # # ]: 0 : if( pPolyPoly )
547 : : {
548 : 0 : bPaintLastPolygon = true; // #107349# Paint last polygon only if loop has generated any output
549 : :
550 [ # # ][ # # ]: 0 : pPolyPoly->Replace( pPolyPoly->GetObject( 1 ), 0 );
551 [ # # ]: 0 : pPolyPoly->Replace( aPoly, 1 );
552 : :
553 [ # # ]: 0 : if( bMtf )
554 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPolyPolygonAction( *pPolyPoly ) );
[ # # ]
555 : : else
556 [ # # ]: 0 : ImplDrawPolyPolygon( *pPolyPoly, pClipPolyPoly );
557 : :
558 : : // #107349# Set fill color _after_ geometry painting:
559 : : // pPolyPoly's geometry is the band from last iteration's
560 : : // aPoly to current iteration's aPoly. The window outdev
561 : : // path (see else below), on the other hand, paints the
562 : : // full aPoly. Thus, here, we're painting the band before
563 : : // the one painted in the window outdev path below. To get
564 : : // matching colors, have to delay color setting here.
565 [ # # ]: 0 : if( bMtf )
566 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), sal_True ) );
[ # # ]
567 : : else
568 [ # # ]: 0 : mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
569 : : }
570 : : else
571 : : {
572 : : // #107349# Set fill color _before_ geometry painting
573 [ # # ]: 0 : if( bMtf )
574 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), sal_True ) );
[ # # ]
575 : : else
576 [ # # ]: 0 : mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
577 : :
578 [ # # ]: 0 : ImplDrawPolygon( aPoly, pClipPolyPoly );
579 : : }
580 : : }
581 : :
582 : : // Falls PolyPolygon-Ausgabe, muessen wir noch ein letztes inneres Polygon zeichnen
583 [ # # ]: 0 : if( pPolyPoly )
584 : : {
585 [ # # ]: 0 : const Polygon& rPoly = pPolyPoly->GetObject( 1 );
586 : :
587 [ # # ][ # # ]: 0 : if( !rPoly.GetBoundRect().IsEmpty() )
[ # # ]
588 : : {
589 : : // #107349# Paint last polygon with end color only if loop
590 : : // has generated output. Otherwise, the current
591 : : // (i.e. start) color is taken, to generate _any_ output.
592 [ # # ]: 0 : if( bPaintLastPolygon )
593 : : {
594 : 0 : nRed = ImplGetGradientColorValue( nEndRed );
595 : 0 : nGreen = ImplGetGradientColorValue( nEndGreen );
596 : 0 : nBlue = ImplGetGradientColorValue( nEndBlue );
597 : : }
598 : :
599 [ # # ]: 0 : if( bMtf )
600 : : {
601 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, nGreen, nBlue ), sal_True ) );
[ # # ]
602 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPolygonAction( rPoly ) );
[ # # ]
603 : : }
604 : : else
605 : : {
606 [ # # ]: 0 : mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
607 [ # # ]: 0 : ImplDrawPolygon( rPoly, pClipPolyPoly );
608 : : }
609 : : }
610 : :
611 [ # # ][ # # ]: 0 : delete pPolyPoly;
612 [ # # ]: 0 : }
613 : 0 : }
614 : :
615 : : // -----------------------------------------------------------------------
616 : :
617 : 255807 : void OutputDevice::DrawGradient( const Rectangle& rRect,
618 : : const Gradient& rGradient )
619 : : {
620 : : OSL_TRACE( "OutputDevice::DrawGradient()" );
621 : : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
622 : : DBG_CHKOBJ( &rGradient, Gradient, NULL );
623 : :
624 [ + - ]: 255807 : if ( mnDrawMode & DRAWMODE_NOGRADIENT )
625 : : return;
626 [ - + ]: 255807 : else if ( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT | DRAWMODE_SETTINGSGRADIENT) )
627 : : {
628 : 0 : Color aColor;
629 : :
630 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_BLACKGRADIENT )
631 : 0 : aColor = Color( COL_BLACK );
632 [ # # ]: 0 : else if ( mnDrawMode & DRAWMODE_WHITEGRADIENT )
633 : 0 : aColor = Color( COL_WHITE );
634 [ # # ]: 0 : else if ( mnDrawMode & DRAWMODE_SETTINGSGRADIENT )
635 : 0 : aColor = GetSettings().GetStyleSettings().GetWindowColor();
636 : :
637 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
638 : : {
639 : 0 : aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
640 : 0 : ( aColor.GetGreen() >> 1 ) | 0x80,
641 : 0 : ( aColor.GetBlue() >> 1 ) | 0x80 );
642 : : }
643 : :
644 [ # # ]: 0 : Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
645 [ # # ]: 0 : SetLineColor( aColor );
646 [ # # ]: 0 : SetFillColor( aColor );
647 [ # # ]: 0 : DrawRect( rRect );
648 [ # # ]: 0 : Pop();
649 : : return;
650 : : }
651 : :
652 [ + - ]: 255807 : Gradient aGradient( rGradient );
653 : :
654 [ - + ]: 255807 : if ( mnDrawMode & ( DRAWMODE_GRAYGRADIENT | DRAWMODE_GHOSTEDGRADIENT ) )
655 : : {
656 : 0 : Color aStartCol( aGradient.GetStartColor() );
657 : 0 : Color aEndCol( aGradient.GetEndColor() );
658 : :
659 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GRAYGRADIENT )
660 : : {
661 [ # # ][ # # ]: 0 : sal_uInt8 cStartLum = aStartCol.GetLuminance(), cEndLum = aEndCol.GetLuminance();
662 : 0 : aStartCol = Color( cStartLum, cStartLum, cStartLum );
663 : 0 : aEndCol = Color( cEndLum, cEndLum, cEndLum );
664 : : }
665 : :
666 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
667 : : {
668 : 0 : aStartCol = Color( ( aStartCol.GetRed() >> 1 ) | 0x80,
669 : 0 : ( aStartCol.GetGreen() >> 1 ) | 0x80,
670 : 0 : ( aStartCol.GetBlue() >> 1 ) | 0x80 );
671 : :
672 : 0 : aEndCol = Color( ( aEndCol.GetRed() >> 1 ) | 0x80,
673 : 0 : ( aEndCol.GetGreen() >> 1 ) | 0x80,
674 : 0 : ( aEndCol.GetBlue() >> 1 ) | 0x80 );
675 : : }
676 : :
677 [ # # ]: 0 : aGradient.SetStartColor( aStartCol );
678 [ # # ]: 0 : aGradient.SetEndColor( aEndCol );
679 : : }
680 : :
681 [ - + ]: 255807 : if( mpMetaFile )
682 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaGradientAction( rRect, aGradient ) );
[ # # ]
683 : :
684 [ + - ][ + - ]: 255807 : if( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
[ - + ][ - + ]
685 : : return;
686 : :
687 : : // Rechteck in Pixel umrechnen
688 [ + - ]: 255807 : Rectangle aRect( ImplLogicToDevicePixel( rRect ) );
689 [ + - ]: 255807 : aRect.Justify();
690 : :
691 : : // Wenn Rechteck leer ist, brauchen wir nichts machen
692 [ + - ][ + - ]: 255807 : if ( !aRect.IsEmpty() )
693 : : {
694 : : // Clip Region sichern
695 [ + - ]: 255807 : Push( PUSH_CLIPREGION );
696 [ + - ]: 255807 : IntersectClipRegion( rRect );
697 : :
698 : : // because we draw with no border line, we have to expand gradient
699 : : // rect to avoid missing lines on the right and bottom edge
700 : 255807 : aRect.Left()--;
701 : 255807 : aRect.Top()--;
702 : 255807 : aRect.Right()++;
703 : 255807 : aRect.Bottom()++;
704 : :
705 : : // we need a graphics
706 [ - + ]: 255807 : if ( !mpGraphics )
707 : : {
708 [ # # ][ # # ]: 0 : if ( !ImplGetGraphics() )
709 : : return;
710 : : }
711 : :
712 [ + - ]: 255807 : if ( mbInitClipRegion )
713 [ + - ]: 255807 : ImplInitClipRegion();
714 : :
715 [ + + ]: 255807 : if ( !mbOutputClipped )
716 : : {
717 : : // Gradienten werden ohne Umrandung gezeichnet
718 [ + + ][ + + ]: 112334 : if ( mbLineColor || mbInitLineColor )
719 : : {
720 [ + - ]: 112307 : mpGraphics->SetLineColor();
721 : 112307 : mbInitLineColor = sal_True;
722 : : }
723 : :
724 : 112334 : mbInitFillColor = sal_True;
725 : :
726 : : // calculate step count if neccessary
727 [ + - ]: 112334 : if ( !aGradient.GetSteps() )
728 [ + - ]: 112334 : aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
729 : :
730 [ - + ][ # # ]: 112334 : if( aGradient.GetStyle() == GradientStyle_LINEAR || aGradient.GetStyle() == GradientStyle_AXIAL )
[ + - ]
731 [ + - ]: 112334 : ImplDrawLinearGradient( aRect, aGradient, sal_False, NULL );
732 : : else
733 [ # # ]: 0 : ImplDrawComplexGradient( aRect, aGradient, sal_False, NULL );
734 : : }
735 : :
736 [ + - ]: 255807 : Pop();
737 : : }
738 : :
739 [ - + ]: 255807 : if( mpAlphaVDev )
740 : : {
741 : : // #i32109#: Make gradient area opaque
742 [ # # ]: 255807 : mpAlphaVDev->ImplFillOpaqueRectangle( rRect );
743 [ + - ][ + - ]: 255807 : }
744 : : }
745 : :
746 : : // -----------------------------------------------------------------------
747 : :
748 : 0 : void OutputDevice::DrawGradient( const PolyPolygon& rPolyPoly,
749 : : const Gradient& rGradient )
750 : : {
751 : : OSL_TRACE( "OutputDevice::DrawGradient()" );
752 : : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
753 : : DBG_CHKOBJ( &rGradient, Gradient, NULL );
754 : :
755 [ # # ]: 0 : if( mbInitClipRegion )
756 : 0 : ImplInitClipRegion();
757 : :
758 [ # # ]: 0 : if( mbOutputClipped )
759 : 0 : return;
760 : :
761 [ # # ]: 0 : if( !mpGraphics )
762 [ # # ]: 0 : if( !ImplGetGraphics() )
763 : 0 : return;
764 : :
765 [ # # ][ # # ]: 0 : if( rPolyPoly.Count() && rPolyPoly[ 0 ].GetSize() && !( mnDrawMode & DRAWMODE_NOGRADIENT ) )
[ # # ][ # # ]
766 : : {
767 [ # # ]: 0 : if ( mnDrawMode & ( DRAWMODE_BLACKGRADIENT | DRAWMODE_WHITEGRADIENT | DRAWMODE_SETTINGSGRADIENT) )
768 : : {
769 : 0 : Color aColor;
770 : :
771 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_BLACKGRADIENT )
772 : 0 : aColor = Color( COL_BLACK );
773 [ # # ]: 0 : else if ( mnDrawMode & DRAWMODE_WHITEGRADIENT )
774 : 0 : aColor = Color( COL_WHITE );
775 [ # # ]: 0 : else if ( mnDrawMode & DRAWMODE_SETTINGSGRADIENT )
776 : 0 : aColor = GetSettings().GetStyleSettings().GetWindowColor();
777 : :
778 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
779 : : {
780 : 0 : aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
781 : 0 : ( aColor.GetGreen() >> 1 ) | 0x80,
782 : 0 : ( aColor.GetBlue() >> 1 ) | 0x80 );
783 : : }
784 : :
785 [ # # ]: 0 : Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
786 [ # # ]: 0 : SetLineColor( aColor );
787 [ # # ]: 0 : SetFillColor( aColor );
788 [ # # ]: 0 : DrawPolyPolygon( rPolyPoly );
789 [ # # ]: 0 : Pop();
790 : : return;
791 : : }
792 : :
793 [ # # ]: 0 : if( mpMetaFile )
794 : : {
795 [ # # ]: 0 : const Rectangle aRect( rPolyPoly.GetBoundRect() );
796 : :
797 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaCommentAction( "XGRAD_SEQ_BEGIN" ) );
[ # # ]
798 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaGradientExAction( rPolyPoly, rGradient ) );
[ # # ]
799 : :
800 [ # # ]: 0 : if( OUTDEV_PRINTER == meOutDevType )
801 : : {
802 [ # # ]: 0 : Push( PUSH_CLIPREGION );
803 [ # # ][ # # ]: 0 : IntersectClipRegion( rPolyPoly );
[ # # ]
804 [ # # ]: 0 : DrawGradient( aRect, rGradient );
805 [ # # ]: 0 : Pop();
806 : : }
807 : : else
808 : : {
809 : 0 : const sal_Bool bOldOutput = IsOutputEnabled();
810 : :
811 [ # # ]: 0 : EnableOutput( sal_False );
812 [ # # ]: 0 : Push( PUSH_RASTEROP );
813 [ # # ]: 0 : SetRasterOp( ROP_XOR );
814 [ # # ]: 0 : DrawGradient( aRect, rGradient );
815 [ # # ]: 0 : SetFillColor( COL_BLACK );
816 [ # # ]: 0 : SetRasterOp( ROP_0 );
817 [ # # ]: 0 : DrawPolyPolygon( rPolyPoly );
818 [ # # ]: 0 : SetRasterOp( ROP_XOR );
819 [ # # ]: 0 : DrawGradient( aRect, rGradient );
820 [ # # ]: 0 : Pop();
821 [ # # ]: 0 : EnableOutput( bOldOutput );
822 : : }
823 : :
824 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaCommentAction( "XGRAD_SEQ_END" ) );
[ # # ]
825 : : }
826 : :
827 [ # # ][ # # ]: 0 : if( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
[ # # ][ # # ]
828 : : return;
829 : :
830 [ # # ]: 0 : Gradient aGradient( rGradient );
831 : :
832 [ # # ]: 0 : if ( mnDrawMode & ( DRAWMODE_GRAYGRADIENT | DRAWMODE_GHOSTEDGRADIENT ) )
833 : : {
834 : 0 : Color aStartCol( aGradient.GetStartColor() );
835 : 0 : Color aEndCol( aGradient.GetEndColor() );
836 : :
837 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GRAYGRADIENT )
838 : : {
839 [ # # ][ # # ]: 0 : sal_uInt8 cStartLum = aStartCol.GetLuminance(), cEndLum = aEndCol.GetLuminance();
840 : 0 : aStartCol = Color( cStartLum, cStartLum, cStartLum );
841 : 0 : aEndCol = Color( cEndLum, cEndLum, cEndLum );
842 : : }
843 : :
844 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDGRADIENT )
845 : : {
846 : 0 : aStartCol = Color( ( aStartCol.GetRed() >> 1 ) | 0x80,
847 : 0 : ( aStartCol.GetGreen() >> 1 ) | 0x80,
848 : 0 : ( aStartCol.GetBlue() >> 1 ) | 0x80 );
849 : :
850 : 0 : aEndCol = Color( ( aEndCol.GetRed() >> 1 ) | 0x80,
851 : 0 : ( aEndCol.GetGreen() >> 1 ) | 0x80,
852 : 0 : ( aEndCol.GetBlue() >> 1 ) | 0x80 );
853 : : }
854 : :
855 [ # # ]: 0 : aGradient.SetStartColor( aStartCol );
856 [ # # ]: 0 : aGradient.SetEndColor( aEndCol );
857 : : }
858 : :
859 [ # # ][ # # ]: 0 : if( OUTDEV_PRINTER == meOutDevType || ImplGetSVData()->maGDIData.mbNoXORClipping )
[ # # ][ # # ]
860 : : {
861 [ # # ]: 0 : const Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
862 : :
863 [ # # ][ # # ]: 0 : if( !Rectangle( PixelToLogic( Point() ), GetOutputSize() ).IsEmpty() )
[ # # ][ # # ]
[ # # ]
864 : : {
865 : : // Rechteck in Pixel umrechnen
866 [ # # ]: 0 : Rectangle aRect( ImplLogicToDevicePixel( aBoundRect ) );
867 [ # # ]: 0 : aRect.Justify();
868 : :
869 : : // Wenn Rechteck leer ist, brauchen wir nichts machen
870 [ # # ][ # # ]: 0 : if ( !aRect.IsEmpty() )
871 : : {
872 [ # # ][ # # ]: 0 : if( !mpGraphics && !ImplGetGraphics() )
[ # # ][ # # ]
873 : : return;
874 : :
875 [ # # ]: 0 : if( mbInitClipRegion )
876 [ # # ]: 0 : ImplInitClipRegion();
877 : :
878 [ # # ]: 0 : if( !mbOutputClipped )
879 : : {
880 [ # # ]: 0 : PolyPolygon aClipPolyPoly( ImplLogicToDevicePixel( rPolyPoly ) );
881 : :
882 : : // Gradienten werden ohne Umrandung gezeichnet
883 [ # # ][ # # ]: 0 : if( mbLineColor || mbInitLineColor )
884 : : {
885 [ # # ]: 0 : mpGraphics->SetLineColor();
886 : 0 : mbInitLineColor = sal_True;
887 : : }
888 : :
889 : 0 : mbInitFillColor = sal_True;
890 : :
891 : : // calculate step count if neccessary
892 [ # # ]: 0 : if ( !aGradient.GetSteps() )
893 [ # # ]: 0 : aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
894 : :
895 [ # # ][ # # ]: 0 : if( aGradient.GetStyle() == GradientStyle_LINEAR || aGradient.GetStyle() == GradientStyle_AXIAL )
[ # # ]
896 [ # # ]: 0 : ImplDrawLinearGradient( aRect, aGradient, sal_False, &aClipPolyPoly );
897 : : else
898 [ # # ][ # # ]: 0 : ImplDrawComplexGradient( aRect, aGradient, sal_False, &aClipPolyPoly );
899 : : }
900 : : }
901 : : }
902 : : }
903 : : else
904 : : {
905 [ # # ]: 0 : const PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
906 [ # # ]: 0 : const Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
907 : 0 : Point aPoint;
908 [ # # ]: 0 : Rectangle aDstRect( aPoint, GetOutputSizePixel() );
909 : :
910 [ # # ]: 0 : aDstRect.Intersection( aBoundRect );
911 : :
912 [ # # ]: 0 : if( OUTDEV_WINDOW == meOutDevType )
913 : : {
914 [ # # ]: 0 : const Region aPaintRgn( ( (Window*) this )->GetPaintRegion() );
915 : :
916 [ # # ][ # # ]: 0 : if( !aPaintRgn.IsNull() )
917 [ # # ][ # # ]: 0 : aDstRect.Intersection( LogicToPixel( aPaintRgn ).GetBoundRect() );
[ # # ][ # # ]
[ # # ]
918 : : }
919 : :
920 [ # # ][ # # ]: 0 : if( !aDstRect.IsEmpty() )
921 : : {
922 : : VirtualDevice* pVDev;
923 [ # # ]: 0 : const Size aDstSize( aDstRect.GetSize() );
924 : :
925 [ # # ][ # # ]: 0 : if( HasAlpha() )
926 : : {
927 : : // #110958# Pay attention to alpha VDevs here, otherwise,
928 : : // background will be wrong: Temp VDev has to have alpha, too.
929 [ # # ][ # # ]: 0 : pVDev = new VirtualDevice( *this, 0, GetAlphaBitCount() > 1 ? 0 : 1 );
[ # # ]
930 : : }
931 : : else
932 : : {
933 : : // nothing special here. Plain VDev
934 [ # # ][ # # ]: 0 : pVDev = new VirtualDevice();
935 : : }
936 : :
937 [ # # ][ # # ]: 0 : if( pVDev->SetOutputSizePixel( aDstSize) )
938 : : {
939 [ # # ]: 0 : MapMode aVDevMap;
940 : 0 : const sal_Bool bOldMap = mbMap;
941 : :
942 [ # # ]: 0 : EnableMapMode( sal_False );
943 : :
944 [ # # ]: 0 : pVDev->DrawOutDev( Point(), aDstSize, aDstRect.TopLeft(), aDstSize, *this );
945 [ # # ]: 0 : pVDev->SetRasterOp( ROP_XOR );
946 [ # # ]: 0 : aVDevMap.SetOrigin( Point( -aDstRect.Left(), -aDstRect.Top() ) );
947 [ # # ]: 0 : pVDev->SetMapMode( aVDevMap );
948 [ # # ]: 0 : pVDev->DrawGradient( aBoundRect, aGradient );
949 [ # # ]: 0 : pVDev->SetFillColor( COL_BLACK );
950 [ # # ]: 0 : pVDev->SetRasterOp( ROP_0 );
951 [ # # ]: 0 : pVDev->DrawPolyPolygon( aPolyPoly );
952 [ # # ]: 0 : pVDev->SetRasterOp( ROP_XOR );
953 [ # # ]: 0 : pVDev->DrawGradient( aBoundRect, aGradient );
954 [ # # ]: 0 : aVDevMap.SetOrigin( Point() );
955 [ # # ]: 0 : pVDev->SetMapMode( aVDevMap );
956 [ # # ]: 0 : DrawOutDev( aDstRect.TopLeft(), aDstSize, Point(), aDstSize, *pVDev );
957 : :
958 [ # # ][ # # ]: 0 : EnableMapMode( bOldMap );
959 : : }
960 : :
961 [ # # ][ # # ]: 0 : delete pVDev;
962 [ # # ]: 0 : }
963 [ # # ][ # # ]: 0 : }
964 : : }
965 : :
966 [ # # ]: 0 : if( mpAlphaVDev )
967 : 0 : mpAlphaVDev->DrawPolyPolygon( rPolyPoly );
968 : : }
969 : :
970 : : // -----------------------------------------------------------------------
971 : :
972 : 0 : void OutputDevice::AddGradientActions( const Rectangle& rRect, const Gradient& rGradient,
973 : : GDIMetaFile& rMtf )
974 : : {
975 : : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
976 : : DBG_CHKOBJ( &rGradient, Gradient, NULL );
977 : :
978 : 0 : Rectangle aRect( rRect );
979 : :
980 [ # # ]: 0 : aRect.Justify();
981 : :
982 : : // Wenn Rechteck leer ist, brauchen wir nichts machen
983 [ # # ][ # # ]: 0 : if ( !aRect.IsEmpty() )
984 : : {
985 [ # # ]: 0 : Gradient aGradient( rGradient );
986 : 0 : GDIMetaFile* pOldMtf = mpMetaFile;
987 : :
988 : 0 : mpMetaFile = &rMtf;
989 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPushAction( PUSH_ALL ) );
[ # # ]
990 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaISectRectClipRegionAction( aRect ) );
[ # # ]
991 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) );
[ # # ]
992 : :
993 : : // because we draw with no border line, we have to expand gradient
994 : : // rect to avoid missing lines on the right and bottom edge
995 : 0 : aRect.Left()--;
996 : 0 : aRect.Top()--;
997 : 0 : aRect.Right()++;
998 : 0 : aRect.Bottom()++;
999 : :
1000 : : // calculate step count if neccessary
1001 [ # # ]: 0 : if ( !aGradient.GetSteps() )
1002 [ # # ]: 0 : aGradient.SetSteps( GRADIENT_DEFAULT_STEPCOUNT );
1003 : :
1004 [ # # ][ # # ]: 0 : if( aGradient.GetStyle() == GradientStyle_LINEAR || aGradient.GetStyle() == GradientStyle_AXIAL )
[ # # ]
1005 [ # # ]: 0 : ImplDrawLinearGradient( aRect, aGradient, sal_True, NULL );
1006 : : else
1007 [ # # ]: 0 : ImplDrawComplexGradient( aRect, aGradient, sal_True, NULL );
1008 : :
1009 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPopAction() );
[ # # ]
1010 [ # # ]: 0 : mpMetaFile = pOldMtf;
1011 : : }
1012 : 0 : }
1013 : :
1014 : : // -----------------------------------------------------------------------
1015 : :
1016 : 616 : void OutputDevice::DrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch )
1017 : : {
1018 : : OSL_TRACE( "OutputDevice::DrawHatch()" );
1019 : : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1020 : :
1021 [ + - ]: 616 : Hatch aHatch( rHatch );
1022 : :
1023 [ - + ]: 616 : if ( mnDrawMode & ( DRAWMODE_BLACKLINE | DRAWMODE_WHITELINE |
1024 : : DRAWMODE_GRAYLINE | DRAWMODE_GHOSTEDLINE |
1025 : : DRAWMODE_SETTINGSLINE ) )
1026 : : {
1027 : 0 : Color aColor( rHatch.GetColor() );
1028 : :
1029 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_BLACKLINE )
1030 : 0 : aColor = Color( COL_BLACK );
1031 [ # # ]: 0 : else if ( mnDrawMode & DRAWMODE_WHITELINE )
1032 : 0 : aColor = Color( COL_WHITE );
1033 [ # # ]: 0 : else if ( mnDrawMode & DRAWMODE_GRAYLINE )
1034 : : {
1035 [ # # ]: 0 : const sal_uInt8 cLum = aColor.GetLuminance();
1036 : 0 : aColor = Color( cLum, cLum, cLum );
1037 : : }
1038 [ # # ]: 0 : else if( mnDrawMode & DRAWMODE_SETTINGSLINE )
1039 : : {
1040 : 0 : aColor = GetSettings().GetStyleSettings().GetFontColor();
1041 : : }
1042 : :
1043 [ # # ]: 0 : if ( mnDrawMode & DRAWMODE_GHOSTEDLINE )
1044 : : {
1045 : 0 : aColor = Color( ( aColor.GetRed() >> 1 ) | 0x80,
1046 : 0 : ( aColor.GetGreen() >> 1 ) | 0x80,
1047 : 0 : ( aColor.GetBlue() >> 1 ) | 0x80);
1048 : : }
1049 : :
1050 [ # # ]: 0 : aHatch.SetColor( aColor );
1051 : : }
1052 : :
1053 [ - + ]: 616 : if( mpMetaFile )
1054 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaHatchAction( rPolyPoly, aHatch ) );
[ # # ]
1055 : :
1056 [ + - ][ + - ]: 616 : if( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
[ - + ][ - + ]
1057 : : return;
1058 : :
1059 [ - + ][ # # ]: 616 : if( !mpGraphics && !ImplGetGraphics() )
[ # # ][ - + ]
1060 : : return;
1061 : :
1062 [ - + ]: 616 : if( mbInitClipRegion )
1063 [ # # ]: 0 : ImplInitClipRegion();
1064 : :
1065 [ - + ]: 616 : if( mbOutputClipped )
1066 : : return;
1067 : :
1068 [ + - ][ + - ]: 616 : if( rPolyPoly.Count() )
1069 : : {
1070 [ + - ]: 616 : PolyPolygon aPolyPoly( LogicToPixel( rPolyPoly ) );
1071 : 616 : GDIMetaFile* pOldMetaFile = mpMetaFile;
1072 : 616 : sal_Bool bOldMap = mbMap;
1073 : :
1074 [ + - ]: 616 : aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME );
1075 [ + - ][ + - ]: 616 : aHatch.SetDistance( ImplLogicWidthToDevicePixel( aHatch.GetDistance() ) );
1076 : :
1077 : 616 : mpMetaFile = NULL;
1078 [ + - ]: 616 : EnableMapMode( sal_False );
1079 [ + - ]: 616 : Push( PUSH_LINECOLOR );
1080 [ + - ]: 616 : SetLineColor( aHatch.GetColor() );
1081 [ + - ]: 616 : ImplInitLineColor();
1082 [ + - ]: 616 : ImplDrawHatch( aPolyPoly, aHatch, sal_False );
1083 [ + - ]: 616 : Pop();
1084 [ + - ]: 616 : EnableMapMode( bOldMap );
1085 [ + - ]: 616 : mpMetaFile = pOldMetaFile;
1086 : : }
1087 : :
1088 [ - + ]: 616 : if( mpAlphaVDev )
1089 [ # # ][ + - ]: 616 : mpAlphaVDev->DrawHatch( rPolyPoly, rHatch );
[ + - ]
1090 : : }
1091 : :
1092 : : // -----------------------------------------------------------------------
1093 : :
1094 : 0 : void OutputDevice::AddHatchActions( const PolyPolygon& rPolyPoly, const Hatch& rHatch,
1095 : : GDIMetaFile& rMtf )
1096 : : {
1097 : : DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
1098 : :
1099 [ # # ]: 0 : PolyPolygon aPolyPoly( rPolyPoly );
1100 [ # # ]: 0 : aPolyPoly.Optimize( POLY_OPTIMIZE_NO_SAME | POLY_OPTIMIZE_CLOSE );
1101 : :
1102 [ # # ][ # # ]: 0 : if( aPolyPoly.Count() )
1103 : : {
1104 : 0 : GDIMetaFile* pOldMtf = mpMetaFile;
1105 : :
1106 : 0 : mpMetaFile = &rMtf;
1107 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPushAction( PUSH_ALL ) );
[ # # ]
1108 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaLineColorAction( rHatch.GetColor(), sal_True ) );
[ # # ]
1109 [ # # ]: 0 : ImplDrawHatch( aPolyPoly, rHatch, sal_True );
1110 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaPopAction() );
[ # # ]
1111 : 0 : mpMetaFile = pOldMtf;
1112 [ # # ]: 0 : }
1113 : 0 : }
1114 : :
1115 : : // -----------------------------------------------------------------------
1116 : :
1117 : 616 : void OutputDevice::ImplDrawHatch( const PolyPolygon& rPolyPoly, const Hatch& rHatch, sal_Bool bMtf )
1118 : : {
1119 [ + - ]: 616 : Rectangle aRect( rPolyPoly.GetBoundRect() );
1120 [ + - ]: 616 : const long nLogPixelWidth = ImplDevicePixelToLogicWidth( 1 );
1121 [ + - ][ + - ]: 616 : const long nWidth = ImplDevicePixelToLogicWidth( Max( ImplLogicWidthToDevicePixel( rHatch.GetDistance() ), 3L ) );
1122 [ + - ][ + + ]: 631400 : Point* pPtBuffer = new Point[ HATCH_MAXPOINTS ];
1123 : 616 : Point aPt1, aPt2, aEndPt1;
1124 : 616 : Size aInc;
1125 : :
1126 : : // Single hatch
1127 : 616 : aRect.Left() -= nLogPixelWidth; aRect.Top() -= nLogPixelWidth; aRect.Right() += nLogPixelWidth; aRect.Bottom() += nLogPixelWidth;
1128 [ + - ]: 616 : ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle(), aPt1, aPt2, aInc, aEndPt1 );
1129 [ + + ]: 64680 : do
[ + - + + ]
1130 : : {
1131 [ + - ]: 32340 : ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
1132 : 32340 : aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
1133 : 32340 : aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
1134 : : }
1135 : 64680 : while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
1136 : :
1137 [ + - ][ - + ]: 616 : if( ( rHatch.GetStyle() == HATCH_DOUBLE ) || ( rHatch.GetStyle() == HATCH_TRIPLE ) )
[ - + ]
1138 : : {
1139 : : // Double hatch
1140 [ # # ]: 0 : ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle() + 900, aPt1, aPt2, aInc, aEndPt1 );
1141 [ # # ]: 0 : do
[ # # # # ]
1142 : : {
1143 [ # # ]: 0 : ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
1144 : 0 : aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
1145 : 0 : aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
1146 : : }
1147 : 0 : while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
1148 : :
1149 [ # # ]: 0 : if( rHatch.GetStyle() == HATCH_TRIPLE )
1150 : : {
1151 : : // Triple hatch
1152 [ # # ]: 0 : ImplCalcHatchValues( aRect, nWidth, rHatch.GetAngle() + 450, aPt1, aPt2, aInc, aEndPt1 );
1153 [ # # ]: 0 : do
[ # # # # ]
1154 : : {
1155 [ # # ]: 0 : ImplDrawHatchLine( Line( aPt1, aPt2 ), rPolyPoly, pPtBuffer, bMtf );
1156 : 0 : aPt1.X() += aInc.Width(); aPt1.Y() += aInc.Height();
1157 : 0 : aPt2.X() += aInc.Width(); aPt2.Y() += aInc.Height();
1158 : : }
1159 : 0 : while( ( aPt1.X() <= aEndPt1.X() ) && ( aPt1.Y() <= aEndPt1.Y() ) );
1160 : : }
1161 : : }
1162 : :
1163 [ + - ]: 616 : delete[] pPtBuffer;
1164 : 616 : }
1165 : :
1166 : : // -----------------------------------------------------------------------
1167 : :
1168 : 616 : void OutputDevice::ImplCalcHatchValues( const Rectangle& rRect, long nDist, sal_uInt16 nAngle10,
1169 : : Point& rPt1, Point& rPt2, Size& rInc, Point& rEndPt1 )
1170 : : {
1171 : 616 : Point aRef;
1172 : 616 : long nAngle = nAngle10 % 1800;
1173 : 616 : long nOffset = 0;
1174 : :
1175 [ - + ]: 616 : if( nAngle > 900 )
1176 : 0 : nAngle -= 1800;
1177 : :
1178 [ + - ]: 616 : aRef = ( !IsRefPoint() ? rRect.TopLeft() : GetRefPoint() );
1179 : :
1180 [ + - ]: 616 : if( 0 == nAngle )
1181 : : {
1182 : 616 : rInc = Size( 0, nDist );
1183 : 616 : rPt1 = rRect.TopLeft();
1184 [ + - ]: 616 : rPt2 = rRect.TopRight();
1185 [ + - ]: 616 : rEndPt1 = rRect.BottomLeft();
1186 : :
1187 [ + - ]: 616 : if( aRef.Y() <= rRect.Top() )
1188 : 616 : nOffset = ( ( rRect.Top() - aRef.Y() ) % nDist );
1189 : : else
1190 : 0 : nOffset = ( nDist - ( ( aRef.Y() - rRect.Top() ) % nDist ) );
1191 : :
1192 : 616 : rPt1.Y() -= nOffset;
1193 : 616 : rPt2.Y() -= nOffset;
1194 : : }
1195 [ # # ]: 0 : else if( 900 == nAngle )
1196 : : {
1197 : 0 : rInc = Size( nDist, 0 );
1198 : 0 : rPt1 = rRect.TopLeft();
1199 [ # # ]: 0 : rPt2 = rRect.BottomLeft();
1200 [ # # ]: 0 : rEndPt1 = rRect.TopRight();
1201 : :
1202 [ # # ]: 0 : if( aRef.X() <= rRect.Left() )
1203 : 0 : nOffset = ( rRect.Left() - aRef.X() ) % nDist;
1204 : : else
1205 : 0 : nOffset = nDist - ( ( aRef.X() - rRect.Left() ) % nDist );
1206 : :
1207 : 0 : rPt1.X() -= nOffset;
1208 : 0 : rPt2.X() -= nOffset;
1209 : : }
1210 [ # # ][ # # ]: 0 : else if( nAngle >= -450 && nAngle <= 450 )
1211 : : {
1212 : 0 : const double fAngle = F_PI1800 * labs( nAngle );
1213 : 0 : const double fTan = tan( fAngle );
1214 : 0 : const long nYOff = FRound( ( rRect.Right() - rRect.Left() ) * fTan );
1215 : : long nPY;
1216 : :
1217 : 0 : rInc = Size( 0, nDist = FRound( nDist / cos( fAngle ) ) );
1218 : :
1219 [ # # ]: 0 : if( nAngle > 0 )
1220 : : {
1221 : 0 : rPt1 = rRect.TopLeft();
1222 : 0 : rPt2 = Point( rRect.Right(), rRect.Top() - nYOff );
1223 : 0 : rEndPt1 = Point( rRect.Left(), rRect.Bottom() + nYOff );
1224 : 0 : nPY = FRound( aRef.Y() - ( ( rPt1.X() - aRef.X() ) * fTan ) );
1225 : : }
1226 : : else
1227 : : {
1228 [ # # ]: 0 : rPt1 = rRect.TopRight();
1229 : 0 : rPt2 = Point( rRect.Left(), rRect.Top() - nYOff );
1230 : 0 : rEndPt1 = Point( rRect.Right(), rRect.Bottom() + nYOff );
1231 : 0 : nPY = FRound( aRef.Y() + ( ( rPt1.X() - aRef.X() ) * fTan ) );
1232 : : }
1233 : :
1234 [ # # ]: 0 : if( nPY <= rPt1.Y() )
1235 : 0 : nOffset = ( rPt1.Y() - nPY ) % nDist;
1236 : : else
1237 : 0 : nOffset = nDist - ( ( nPY - rPt1.Y() ) % nDist );
1238 : :
1239 : 0 : rPt1.Y() -= nOffset;
1240 : 0 : rPt2.Y() -= nOffset;
1241 : : }
1242 : : else
1243 : : {
1244 : 0 : const double fAngle = F_PI1800 * labs( nAngle );
1245 : 0 : const double fTan = tan( fAngle );
1246 : 0 : const long nXOff = FRound( ( rRect.Bottom() - rRect.Top() ) / fTan );
1247 : : long nPX;
1248 : :
1249 : 0 : rInc = Size( nDist = FRound( nDist / sin( fAngle ) ), 0 );
1250 : :
1251 [ # # ]: 0 : if( nAngle > 0 )
1252 : : {
1253 : 0 : rPt1 = rRect.TopLeft();
1254 : 0 : rPt2 = Point( rRect.Left() - nXOff, rRect.Bottom() );
1255 : 0 : rEndPt1 = Point( rRect.Right() + nXOff, rRect.Top() );
1256 : 0 : nPX = FRound( aRef.X() - ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
1257 : : }
1258 : : else
1259 : : {
1260 [ # # ]: 0 : rPt1 = rRect.BottomLeft();
1261 : 0 : rPt2 = Point( rRect.Left() - nXOff, rRect.Top() );
1262 : 0 : rEndPt1 = Point( rRect.Right() + nXOff, rRect.Bottom() );
1263 : 0 : nPX = FRound( aRef.X() + ( ( rPt1.Y() - aRef.Y() ) / fTan ) );
1264 : : }
1265 : :
1266 [ # # ]: 0 : if( nPX <= rPt1.X() )
1267 : 0 : nOffset = ( rPt1.X() - nPX ) % nDist;
1268 : : else
1269 : 0 : nOffset = nDist - ( ( nPX - rPt1.X() ) % nDist );
1270 : :
1271 : 0 : rPt1.X() -= nOffset;
1272 : 0 : rPt2.X() -= nOffset;
1273 : : }
1274 : 616 : }
1275 : :
1276 : : // ------------------------------------------------------------------------
1277 : :
1278 : 32340 : void OutputDevice::ImplDrawHatchLine( const Line& rLine, const PolyPolygon& rPolyPoly,
1279 : : Point* pPtBuffer, sal_Bool bMtf )
1280 : : {
1281 : : double fX, fY;
1282 : 32340 : long nAdd, nPCounter = 0;
1283 : :
1284 [ + - ][ + + ]: 64680 : for( long nPoly = 0, nPolyCount = rPolyPoly.Count(); nPoly < nPolyCount; nPoly++ )
1285 : : {
1286 [ + - ]: 32340 : const Polygon& rPoly = rPolyPoly[ (sal_uInt16) nPoly ];
1287 : :
1288 [ + - ][ + - ]: 32340 : if( rPoly.GetSize() > 1 )
1289 : : {
1290 [ + - ]: 32340 : Line aCurSegment( rPoly[ 0 ], Point() );
1291 : :
1292 [ + + ][ + - ]: 161700 : for( long i = 1, nCount = rPoly.GetSize(); i <= nCount; i++ )
1293 : : {
1294 [ + - ]: 129360 : aCurSegment.SetEnd( rPoly[ (sal_uInt16)( i % nCount ) ] );
1295 : 129360 : nAdd = 0;
1296 : :
1297 [ + + ][ + - ]: 129360 : if( rLine.Intersection( aCurSegment, fX, fY ) )
1298 : : {
1299 [ + - - + ]: 126896 : if( ( fabs( fX - aCurSegment.GetStart().X() ) <= 0.0000001 ) &&
[ - + ]
1300 : 63448 : ( fabs( fY - aCurSegment.GetStart().Y() ) <= 0.0000001 ) )
1301 : : {
1302 [ # # ][ # # ]: 0 : const Line aPrevSegment( rPoly[ (sal_uInt16)( ( i > 1 ) ? ( i - 2 ) : ( nCount - 1 ) ) ], aCurSegment.GetStart() );
1303 [ # # ]: 0 : const double fPrevDistance = rLine.GetDistance( aPrevSegment.GetStart() );
1304 [ # # ]: 0 : const double fCurDistance = rLine.GetDistance( aCurSegment.GetEnd() );
1305 : :
1306 [ # # ][ # # ]: 0 : if( ( fPrevDistance <= 0.0 && fCurDistance > 0.0 ) ||
[ # # ][ # # ]
1307 : : ( fPrevDistance > 0.0 && fCurDistance < 0.0 ) )
1308 : : {
1309 : 0 : nAdd = 1;
1310 : : }
1311 : : }
1312 [ + - - + ]: 126896 : else if( ( fabs( fX - aCurSegment.GetEnd().X() ) <= 0.0000001 ) &&
[ - + ]
1313 : 63448 : ( fabs( fY - aCurSegment.GetEnd().Y() ) <= 0.0000001 ) )
1314 : : {
1315 [ # # ]: 0 : const Line aNextSegment( aCurSegment.GetEnd(), rPoly[ (sal_uInt16)( ( i + 1 ) % nCount ) ] );
1316 : :
1317 [ # # ][ # # ]: 0 : if( ( fabs( rLine.GetDistance( aNextSegment.GetEnd() ) ) <= 0.0000001 ) &&
[ # # ][ # # ]
1318 [ # # ]: 0 : ( rLine.GetDistance( aCurSegment.GetStart() ) > 0.0 ) )
1319 : : {
1320 : 0 : nAdd = 1;
1321 : : }
1322 : : }
1323 : : else
1324 : 63448 : nAdd = 1;
1325 : :
1326 [ + - ]: 63448 : if( nAdd )
1327 : 63448 : pPtBuffer[ nPCounter++ ] = Point( FRound( fX ), FRound( fY ) );
1328 : : }
1329 : :
1330 : 129360 : aCurSegment.SetStart( aCurSegment.GetEnd() );
1331 : : }
1332 : : }
1333 : : }
1334 : :
1335 [ + + ]: 32340 : if( nPCounter > 1 )
1336 : : {
1337 [ + - ]: 31724 : qsort( pPtBuffer, nPCounter, sizeof( Point ), ImplHatchCmpFnc );
1338 : :
1339 [ - + ]: 31724 : if( nPCounter & 1 )
1340 : 0 : nPCounter--;
1341 : :
1342 [ - + ]: 31724 : if( bMtf )
1343 : : {
1344 [ # # ]: 0 : for( long i = 0; i < nPCounter; i += 2 )
1345 [ # # ][ # # ]: 0 : mpMetaFile->AddAction( new MetaLineAction( pPtBuffer[ i ], pPtBuffer[ i + 1 ] ) );
[ # # ]
1346 : : }
1347 : : else
1348 : : {
1349 [ + + ]: 63448 : for( long i = 0; i < nPCounter; i += 2 )
1350 : : {
1351 [ - + ]: 31724 : if( mpPDFWriter )
1352 : : {
1353 [ # # ]: 0 : mpPDFWriter->drawLine( pPtBuffer[ i ], pPtBuffer[ i+1 ] );
1354 : : }
1355 : : else
1356 : : {
1357 [ + - ]: 31724 : const Point aPt1( ImplLogicToDevicePixel( pPtBuffer[ i ] ) );
1358 [ + - ]: 31724 : const Point aPt2( ImplLogicToDevicePixel( pPtBuffer[ i + 1 ] ) );
1359 [ + - ]: 31724 : mpGraphics->DrawLine( aPt1.X(), aPt1.Y(), aPt2.X(), aPt2.Y(), this );
1360 : : }
1361 : : }
1362 : : }
1363 : : }
1364 : 32340 : }
1365 : :
1366 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|