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