Author: alg
Date: Tue Oct  2 09:21:47 2012
New Revision: 1392804

URL: http://svn.apache.org/viewvc?rev=1392804&view=rev
Log:
#120957# Added Reginas corrections for gradient colors for linear gradients in 
VCL renderers
Patch by: Regina
Review by: alg

Modified:
    incubator/ooo/trunk/main/vcl/source/gdi/outdev4.cxx

Modified: incubator/ooo/trunk/main/vcl/source/gdi/outdev4.cxx
URL: 
http://svn.apache.org/viewvc/incubator/ooo/trunk/main/vcl/source/gdi/outdev4.cxx?rev=1392804&r1=1392803&r2=1392804&view=diff
==============================================================================
--- incubator/ooo/trunk/main/vcl/source/gdi/outdev4.cxx (original)
+++ incubator/ooo/trunk/main/vcl/source/gdi/outdev4.cxx Tue Oct  2 09:21:47 2012
@@ -170,12 +170,8 @@ void OutputDevice::ImplDrawLinearGradien
                                                                                
   const Gradient& rGradient,
                                                                                
   sal_Bool bMtf, const PolyPolygon* pClipPolyPoly )
 {
-       // rotiertes BoundRect ausrechnen
+       // get BoundRect of rotated rectangle
        Rectangle aRect = rRect;
-       aRect.Left()--;
-       aRect.Top()--;
-       aRect.Right()++;
-       aRect.Bottom()++;
        sal_uInt16      nAngle = rGradient.GetAngle() % 3600;
        double  fAngle  = nAngle * F_PI1800;
        double  fWidth  = aRect.GetWidth();
@@ -191,224 +187,205 @@ void OutputDevice::ImplDrawLinearGradien
        aRect.Top()    -= (long)fDY;
        aRect.Bottom() += (long)fDY;
 
-       // Rand berechnen und Rechteck neu setzen
+       sal_Bool        bLinear = ( rGradient.GetStyle() == GRADIENT_LINEAR );
+       double          fBorder = rGradient.GetBorder() * aRect.GetHeight() / 
100.0;
        Point           aCenter = rRect.Center();
-       Rectangle       aFullRect = aRect;
-       long            nBorder = (long)rGradient.GetBorder() * 
aRect.GetHeight() / 100;
-       sal_Bool                bLinear;
+    if ( !bLinear )
+    {
+        fBorder /= 2.0;
+    }
+    Rectangle aMirrorRect = aRect; // used in style axial
+    aMirrorRect.Top() = ( aRect.Top() + aRect.Bottom() ) / 2;
+    if ( !bLinear )
+    {
+        aRect.Bottom() = aMirrorRect.Top();
+    }
 
-       // Rand berechnen und Rechteck neu setzen fuer linearen Farbverlauf
-       if ( rGradient.GetStyle() == GRADIENT_LINEAR )
-       {
-               bLinear = sal_True;
-               aRect.Top() += nBorder;
-       }
-       // Rand berechnen und Rechteck neu setzen fuer axiale Farbverlauf
-       else
-       {
-               bLinear = sal_False;
-               nBorder >>= 1;
+       // Intensitaeten von Start- und Endfarbe ggf. aendern
+       long    nFactor;
+       Color   aStartCol       = rGradient.GetStartColor();
+       Color   aEndCol         = rGradient.GetEndColor();
+       long    nStartRed       = aStartCol.GetRed();
+       long    nStartGreen = aStartCol.GetGreen();
+       long    nStartBlue      = aStartCol.GetBlue();
+       long    nEndRed         = aEndCol.GetRed();
+       long    nEndGreen       = aEndCol.GetGreen();
+       long    nEndBlue        = aEndCol.GetBlue();
+            nFactor    = rGradient.GetStartIntensity();
+                       nStartRed       = (nStartRed   * nFactor) / 100;
+                       nStartGreen = (nStartGreen * nFactor) / 100;
+                       nStartBlue      = (nStartBlue  * nFactor) / 100;
+                       nFactor         = rGradient.GetEndIntensity();
+                       nEndRed         = (nEndRed       * nFactor) / 100;
+                       nEndGreen       = (nEndGreen * nFactor) / 100;
+                       nEndBlue        = (nEndBlue  * nFactor) / 100;
 
-               aRect.Top()    += nBorder;
-               aRect.Bottom() -= nBorder;
-       }
+    // gradient style axial has exchanged start and end colors
+    if ( !bLinear)
+    {
+        long nTempColor = nStartRed;
+        nStartRed = nEndRed;
+        nEndRed = nTempColor;
+        nTempColor = nStartGreen;
+        nStartGreen = nEndGreen;
+        nEndGreen = nTempColor;
+        nTempColor = nStartBlue;
+        nStartBlue = nEndBlue;
+        nEndBlue = nTempColor;
+    }
 
-       // Top darf nicht groesser als Bottom sein
-       aRect.Top() = Min( aRect.Top(), (long)(aRect.Bottom() - 1) );
+    sal_uInt8   nRed;
+    sal_uInt8   nGreen;
+    sal_uInt8   nBlue;
+
+    // Create border
+    Rectangle aBorderRect = aRect;
+    Polygon     aPoly( 4 );
+    if (fBorder > 0.0)
+    {
+        nRed        = (sal_uInt8)nStartRed;
+        nGreen      = (sal_uInt8)nStartGreen;
+        nBlue       = (sal_uInt8)nStartBlue;
+        if ( bMtf )
+            mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, 
nGreen, nBlue ), sal_True ) );
+        else
+            mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
 
+        aBorderRect.Bottom() = (long)( aBorderRect.Top() + fBorder );
+        aRect.Top() = aBorderRect.Bottom();
+        aPoly[0] = aBorderRect.TopLeft();
+        aPoly[1] = aBorderRect.TopRight();
+        aPoly[2] = aBorderRect.BottomRight();
+        aPoly[3] = aBorderRect.BottomLeft();
+        aPoly.Rotate( aCenter, nAngle );
+        if ( bMtf )
+            mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+        else
+            ImplDrawPolygon( aPoly, pClipPolyPoly );
+        if ( !bLinear)
+        {
+            aBorderRect = aMirrorRect;
+            aBorderRect.Top() = (long) ( aBorderRect.Bottom() - fBorder );
+            aMirrorRect.Bottom() = aBorderRect.Top();
+            aPoly[0] = aBorderRect.TopLeft();
+            aPoly[1] = aBorderRect.TopRight();
+            aPoly[2] = aBorderRect.BottomRight();
+            aPoly[3] = aBorderRect.BottomLeft();
+            aPoly.Rotate( aCenter, nAngle );
+            if ( bMtf )
+                mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+            else
+                ImplDrawPolygon( aPoly, pClipPolyPoly );
+        }
+    }
+    
+    // calculate step count
+    long    nStepCount  = rGradient.GetSteps();
+       // generate nStepCount, if not passed
        long nMinRect = aRect.GetHeight();
-
-       // Intensitaeten von Start- und Endfarbe ggf. aendern und
-       // Farbschrittweiten berechnen
-       long                    nFactor;
-       Color                   aStartCol       = rGradient.GetStartColor();
-       Color                   aEndCol         = rGradient.GetEndColor();
-       long                    nStartRed       = aStartCol.GetRed();
-       long                    nStartGreen = aStartCol.GetGreen();
-       long                    nStartBlue      = aStartCol.GetBlue();
-       long                    nEndRed         = aEndCol.GetRed();
-       long                    nEndGreen       = aEndCol.GetGreen();
-       long                    nEndBlue        = aEndCol.GetBlue();
-                                       nFactor         = 
rGradient.GetStartIntensity();
-                                       nStartRed       = (nStartRed   * 
nFactor) / 100;
-                                       nStartGreen = (nStartGreen * nFactor) / 
100;
-                                       nStartBlue      = (nStartBlue  * 
nFactor) / 100;
-                                       nFactor         = 
rGradient.GetEndIntensity();
-                                       nEndRed         = (nEndRed       * 
nFactor) / 100;
-                                       nEndGreen       = (nEndGreen * nFactor) 
/ 100;
-                                       nEndBlue        = (nEndBlue  * nFactor) 
/ 100;
-       long                    nRedSteps       = nEndRed       - nStartRed;
-       long                    nGreenSteps = nEndGreen - nStartGreen;
-       long                    nBlueSteps      = nEndBlue      - nStartBlue;
-       long            nStepCount = rGradient.GetSteps();
-
-       // Bei nicht linearen Farbverlaeufen haben wir nur die halben Steps
-       // pro Farbe
-       if ( !bLinear )
-       {
-               nRedSteps       <<= 1;
-               nGreenSteps <<= 1;
-               nBlueSteps      <<= 1;
-       }
-
-       // Anzahl der Schritte berechnen, falls nichts uebergeben wurde
        if ( !nStepCount )
        {
-               long nInc;
-
+               long nInc = 1;
                if ( meOutDevType != OUTDEV_PRINTER && !bMtf )
         {
                        nInc = (nMinRect < 50) ? 2 : 4;
         }
                else
         {
-            // #105998# Use display-equivalent step size calculation
+            // Use display-equivalent step size calculation
                        nInc = (nMinRect < 800) ? 10 : 20;
         }
-
-               if ( !nInc )
-                       nInc = 1;
-
                nStepCount = nMinRect / nInc;
        }
-       // minimal drei Schritte und maximal die Anzahl der Farbunterschiede
-       long nSteps = Max( nStepCount, 2L );
-       long nCalcSteps  = Abs( nRedSteps );
-       long nTempSteps = Abs( nGreenSteps );
-       if ( nTempSteps > nCalcSteps )
-               nCalcSteps = nTempSteps;
-       nTempSteps = Abs( nBlueSteps );
-       if ( nTempSteps > nCalcSteps )
-               nCalcSteps = nTempSteps;
-       if ( nCalcSteps < nSteps )
-               nSteps = nCalcSteps;
-       if ( !nSteps )
-               nSteps = 1;
 
-       // Falls axialer Farbverlauf, muss die Schrittanzahl ungerade sein
-       if ( !bLinear && !(nSteps & 1) )
-               nSteps++;
-
-       // Berechnung ueber Double-Addition wegen Genauigkeit
-       double fScanLine = aRect.Top();
-       double fScanInc  = (double)aRect.GetHeight() / (double)nSteps;
-
-       // Startfarbe berechnen und setzen
-       sal_uInt8       nRed;
-       sal_uInt8       nGreen;
-       sal_uInt8       nBlue;
-       long    nSteps2;
-       long    nStepsHalf = 0;
-       if ( bLinear )
-       {
-               // Um 1 erhoeht, um die Border innerhalb der Schleife
-               // zeichnen zu koennen
-               nSteps2         = nSteps + 1;
-               nRed            = (sal_uInt8)nStartRed;
-               nGreen          = (sal_uInt8)nStartGreen;
-               nBlue           = (sal_uInt8)nStartBlue;
-       }
-       else
-       {
-               // Um 2 erhoeht, um die Border innerhalb der Schleife
-               // zeichnen zu koennen
-               nSteps2         = nSteps + 2;
-               nRed            = (sal_uInt8)nEndRed;
-               nGreen          = (sal_uInt8)nEndGreen;
-               nBlue           = (sal_uInt8)nEndBlue;
-               nStepsHalf      = nSteps >> 1;
-       }
-
-       if ( bMtf )
-               mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, 
nGreen, nBlue ), sal_True ) );
-       else
-               mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) 
);
-
-       // Startpolygon erzeugen (== Borderpolygon)
-       Polygon         aPoly( 4 );
-       Polygon         aTempPoly( 2 );
-       aPoly[0] = aFullRect.TopLeft();
-       aPoly[1] = aFullRect.TopRight();
-       aPoly[2] = aRect.TopRight();
-       aPoly[3] = aRect.TopLeft();
-       aPoly.Rotate( aCenter, nAngle );
-
-       // Schleife, um rotierten Verlauf zu fuellen
-       for ( long i = 0; i < nSteps2; i++ )
-       {
-               // berechnetesPolygon ausgeben
-               if ( bMtf )
-                       mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
-               else
-                       ImplDrawPolygon( aPoly, pClipPolyPoly );
-
-               // neues Polygon berechnen
-               aRect.Top() = (long)(fScanLine += fScanInc);
+       // minimal three steps and maximal as max color steps
+       long   nAbsRedSteps   = Abs( nEndRed   - nStartRed );
+       long   nAbsGreenSteps = Abs( nEndGreen - nStartGreen );
+       long   nAbsBlueSteps  = Abs( nEndBlue  - nStartBlue );
+       long   nMaxColorSteps = Max( nAbsRedSteps , nAbsGreenSteps );
+    nMaxColorSteps = Max( nMaxColorSteps, nAbsBlueSteps );
+       long nSteps = Min( nStepCount, nMaxColorSteps );
+    if ( nSteps < 3)
+    {
+        nSteps = 3;
+    }
 
-               // unteren Rand komplett fuellen
-               if ( i == nSteps )
-               {
-                       aTempPoly[0] = aFullRect.BottomLeft();
-                       aTempPoly[1] = aFullRect.BottomRight();
-               }
-               else
-               {
-                       aTempPoly[0] = aRect.TopLeft();
-                       aTempPoly[1] = aRect.TopRight();
-               }
-               aTempPoly.Rotate( aCenter, nAngle );
+    double fScanInc = ((double)aRect.GetHeight()) / (double) nSteps;
+    double fGradientLine = (double)aRect.Top();
+    double fMirrorGradientLine = (double) aMirrorRect.Bottom();
+
+    double fAlpha = 0.0;
+    const double fStepsMinus1 = ((double)nSteps) - 1.0;
+    double fTempColor;
+    if ( !bLinear)
+    {
+        nSteps -= 1; // draw middle polygons as one polygon after loop to 
avoid gap
+    }
+    for ( long i = 0; i < nSteps; i++ )
+    {
+        // linear interpolation of color
+        fAlpha = ((double)i) / fStepsMinus1;
+        fTempColor = ((double)nStartRed) * (1.0-fAlpha) + ((double)nEndRed) * 
fAlpha;
+        nRed = ImplGetGradientColorValue((long)fTempColor);
+        fTempColor = ((double)nStartGreen) * (1.0-fAlpha) + 
((double)nEndGreen) * fAlpha;
+        nGreen = ImplGetGradientColorValue((long)fTempColor);
+        fTempColor = ((double)nStartBlue) * (1.0-fAlpha) + ((double)nEndBlue) 
* fAlpha;
+        nBlue = ImplGetGradientColorValue((long)fTempColor);
+        if ( bMtf )
+            mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, 
nGreen, nBlue ), sal_True ) );
+        else
+            mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
 
-               aPoly[0] = aPoly[3];
-               aPoly[1] = aPoly[2];
-               aPoly[2] = aTempPoly[1];
-               aPoly[3] = aTempPoly[0];
-
-               // Farbintensitaeten aendern...
-               // fuer lineare FV
-               if ( bLinear )
-               {
-                       nRed    = ImplGetGradientColorValue( 
nStartRed+((nRedSteps*i)/nSteps2) );
-                       nGreen  = ImplGetGradientColorValue( 
nStartGreen+((nGreenSteps*i)/nSteps2) );
-                       nBlue   = ImplGetGradientColorValue( 
nStartBlue+((nBlueSteps*i)/nSteps2) );
-               }
-               // fuer radiale FV
-               else
-               {
-                       // fuer axiale FV muss die letzte Farbe der ersten
-                       // Farbe entsprechen
-            // #107350# Setting end color one step earlier, as the
-            // last time we get here, we drop out of the loop later
-            // on.
-                       if ( i >= nSteps )
-                       {
-                               nRed    = (sal_uInt8)nEndRed;
-                               nGreen  = (sal_uInt8)nEndGreen;
-                               nBlue   = (sal_uInt8)nEndBlue;
-                       }
-                       else
-                       {
-                               if ( i <= nStepsHalf )
-                               {
-                                       nRed    = ImplGetGradientColorValue( 
nEndRed-((nRedSteps*i)/nSteps2) );
-                                       nGreen  = ImplGetGradientColorValue( 
nEndGreen-((nGreenSteps*i)/nSteps2) );
-                                       nBlue   = ImplGetGradientColorValue( 
nEndBlue-((nBlueSteps*i)/nSteps2) );
-                               }
-                               // genau die Mitte und hoeher
-                               else
-                               {
-                                       long i2 = i - nStepsHalf;
-                                       nRed    = ImplGetGradientColorValue( 
nStartRed+((nRedSteps*i2)/nSteps2) );
-                                       nGreen  = ImplGetGradientColorValue( 
nStartGreen+((nGreenSteps*i2)/nSteps2) );
-                                       nBlue   = ImplGetGradientColorValue( 
nStartBlue+((nBlueSteps*i2)/nSteps2) );
-                               }
-                       }
-               }
+        // Polygon for this color step
+        aRect.Top() = (long)( fGradientLine + ((double) i) * fScanInc );
+        aRect.Bottom() = (long)( fGradientLine + ( ((double) i) + 1.0 ) * 
fScanInc );
+        aPoly[0] = aRect.TopLeft();
+        aPoly[1] = aRect.TopRight();
+        aPoly[2] = aRect.BottomRight();
+        aPoly[3] = aRect.BottomLeft();
+        aPoly.Rotate( aCenter, nAngle );
+        if ( bMtf )
+            mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+        else
+            ImplDrawPolygon( aPoly, pClipPolyPoly );
+        if ( !bLinear )
+        {
+            aMirrorRect.Bottom() = (long)( fMirrorGradientLine - ((double) i) 
* fScanInc );
+            aMirrorRect.Top() = (long)( fMirrorGradientLine - (((double) i) + 
1.0)* fScanInc );
+            aPoly[0] = aMirrorRect.TopLeft();
+            aPoly[1] = aMirrorRect.TopRight();
+            aPoly[2] = aMirrorRect.BottomRight();
+            aPoly[3] = aMirrorRect.BottomLeft();
+            aPoly.Rotate( aCenter, nAngle );
+            if ( bMtf )
+                mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+            else
+                ImplDrawPolygon( aPoly, pClipPolyPoly );
+        }
+    }
+    if ( !bLinear)
+    {
+        // draw middle polygon with end color
+        nRed = ImplGetGradientColorValue(nEndRed);
+        nGreen = ImplGetGradientColorValue(nEndGreen);
+        nBlue = ImplGetGradientColorValue(nEndBlue);
+        if ( bMtf )
+            mpMetaFile->AddAction( new MetaFillColorAction( Color( nRed, 
nGreen, nBlue ), sal_True ) );
+        else
+            mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, nBlue ) );
 
-               if ( bMtf )
-                       mpMetaFile->AddAction( new MetaFillColorAction( Color( 
nRed, nGreen, nBlue ), sal_True ) );
-               else
-                       mpGraphics->SetFillColor( MAKE_SALCOLOR( nRed, nGreen, 
nBlue ) );
-       }
+        aRect.Top() = (long)( fGradientLine + ((double)nSteps) * fScanInc );
+        aRect.Bottom() = (long)( fMirrorGradientLine - ((double) nSteps) * 
fScanInc );
+        aPoly[0] = aRect.TopLeft();
+        aPoly[1] = aRect.TopRight();
+        aPoly[2] = aRect.BottomRight();
+        aPoly[3] = aRect.BottomLeft();
+        aPoly.Rotate( aCenter, nAngle );
+        if ( bMtf )
+            mpMetaFile->AddAction( new MetaPolygonAction( aPoly ) );
+        else
+            ImplDrawPolygon( aPoly, pClipPolyPoly );
+    }
 }
 
 // -----------------------------------------------------------------------


Reply via email to