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