LCOV - code coverage report
Current view: top level - drawinglayer/source/primitive2d - fillgradientprimitive2d.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 61 126 48.4 %
Date: 2015-06-13 12:38:46 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
      21             : #include <basegfx/polygon/b2dpolygon.hxx>
      22             : #include <basegfx/polygon/b2dpolygontools.hxx>
      23             : #include <drawinglayer/texture/texture.hxx>
      24             : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
      25             : #include <basegfx/tools/canvastools.hxx>
      26             : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
      27             : 
      28             : 
      29             : 
      30             : using namespace com::sun::star;
      31             : 
      32             : 
      33             : 
      34             : namespace drawinglayer
      35             : {
      36             :     namespace primitive2d
      37             :     {
      38        1765 :         void FillGradientPrimitive2D::generateMatricesAndColors(
      39             :             std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries,
      40             :             basegfx::BColor& rOuterColor) const
      41             :         {
      42        1765 :             rEntries.clear();
      43             : 
      44             :             // make sure steps is not too high/low
      45        1765 :             const basegfx::BColor aStart(getFillGradient().getStartColor());
      46        3530 :             const basegfx::BColor aEnd(getFillGradient().getEndColor());
      47        1765 :             const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5));
      48        1765 :             sal_uInt32 nSteps(getFillGradient().getSteps());
      49             : 
      50        1765 :             if(nSteps == 0)
      51             :             {
      52        1763 :                 nSteps = nMaxSteps;
      53             :             }
      54             : 
      55        1765 :             if(nSteps < 2)
      56             :             {
      57           0 :                 nSteps = 2;
      58             :             }
      59             : 
      60        1765 :             if(nSteps > nMaxSteps)
      61             :             {
      62           0 :                 nSteps = nMaxSteps;
      63             :             }
      64             : 
      65        1765 :             nSteps = std::max(sal_uInt32(1), nSteps);
      66             : 
      67        1765 :             switch(getFillGradient().getStyle())
      68             :             {
      69             :                 case attribute::GRADIENTSTYLE_LINEAR:
      70             :                 {
      71             :                     texture::GeoTexSvxGradientLinear aGradient(
      72        1404 :                         getDefinitionRange(),
      73        1404 :                         getOutputRange(),
      74             :                         aStart,
      75             :                         aEnd,
      76             :                         nSteps,
      77        1404 :                         getFillGradient().getBorder(),
      78        4212 :                         getFillGradient().getAngle());
      79        1404 :                     aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
      80        1404 :                     break;
      81             :                 }
      82             :                 case attribute::GRADIENTSTYLE_AXIAL:
      83             :                 {
      84             :                     texture::GeoTexSvxGradientAxial aGradient(
      85         361 :                         getDefinitionRange(),
      86         361 :                         getOutputRange(),
      87             :                         aStart,
      88             :                         aEnd,
      89             :                         nSteps,
      90         361 :                         getFillGradient().getBorder(),
      91        1083 :                         getFillGradient().getAngle());
      92         361 :                     aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
      93         361 :                     break;
      94             :                 }
      95             :                 case attribute::GRADIENTSTYLE_RADIAL:
      96             :                 {
      97             :                     texture::GeoTexSvxGradientRadial aGradient(
      98           0 :                         getDefinitionRange(),
      99             :                         aStart,
     100             :                         aEnd,
     101             :                         nSteps,
     102           0 :                         getFillGradient().getBorder(),
     103           0 :                         getFillGradient().getOffsetX(),
     104           0 :                         getFillGradient().getOffsetY());
     105           0 :                     aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
     106           0 :                     break;
     107             :                 }
     108             :                 case attribute::GRADIENTSTYLE_ELLIPTICAL:
     109             :                 {
     110             :                     texture::GeoTexSvxGradientElliptical aGradient(
     111           0 :                         getDefinitionRange(),
     112             :                         aStart,
     113             :                         aEnd,
     114             :                         nSteps,
     115           0 :                         getFillGradient().getBorder(),
     116           0 :                         getFillGradient().getOffsetX(),
     117           0 :                         getFillGradient().getOffsetY(),
     118           0 :                         getFillGradient().getAngle());
     119           0 :                     aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
     120           0 :                     break;
     121             :                 }
     122             :                 case attribute::GRADIENTSTYLE_SQUARE:
     123             :                 {
     124             :                     texture::GeoTexSvxGradientSquare aGradient(
     125           0 :                         getDefinitionRange(),
     126             :                         aStart,
     127             :                         aEnd,
     128             :                         nSteps,
     129           0 :                         getFillGradient().getBorder(),
     130           0 :                         getFillGradient().getOffsetX(),
     131           0 :                         getFillGradient().getOffsetY(),
     132           0 :                         getFillGradient().getAngle());
     133           0 :                     aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
     134           0 :                     break;
     135             :                 }
     136             :                 case attribute::GRADIENTSTYLE_RECT:
     137             :                 {
     138             :                     texture::GeoTexSvxGradientRect aGradient(
     139           0 :                         getDefinitionRange(),
     140             :                         aStart,
     141             :                         aEnd,
     142             :                         nSteps,
     143           0 :                         getFillGradient().getBorder(),
     144           0 :                         getFillGradient().getOffsetX(),
     145           0 :                         getFillGradient().getOffsetY(),
     146           0 :                         getFillGradient().getAngle());
     147           0 :                     aGradient.appendTransformationsAndColors(rEntries, rOuterColor);
     148           0 :                     break;
     149             :                 }
     150        1765 :             }
     151        1765 :         }
     152             : 
     153        1765 :         Primitive2DSequence FillGradientPrimitive2D::createOverlappingFill(
     154             :             const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries,
     155             :             const basegfx::BColor& rOuterColor,
     156             :             const basegfx::B2DPolygon& rUnitPolygon) const
     157             :         {
     158             :             // prepare return value
     159        1765 :             Primitive2DSequence aRetval(rEntries.size() + 1);
     160             : 
     161             :             // create solid fill with outmost color
     162        3530 :             aRetval[0] = Primitive2DReference(
     163             :                 new PolyPolygonColorPrimitive2D(
     164             :                     basegfx::B2DPolyPolygon(
     165        1765 :                         basegfx::tools::createPolygonFromRect(getOutputRange())),
     166        5295 :                     rOuterColor));
     167             : 
     168             :             // create solid fill steps
     169      220712 :             for(size_t a(0); a < rEntries.size(); a++)
     170             :             {
     171             :                 // create part polygon
     172      218947 :                 basegfx::B2DPolygon aNewPoly(rUnitPolygon);
     173             : 
     174      218947 :                 aNewPoly.transform(rEntries[a].maB2DHomMatrix);
     175             : 
     176             :                 // create solid fill
     177      437894 :                 aRetval[a + 1] = Primitive2DReference(
     178             :                     new PolyPolygonColorPrimitive2D(
     179             :                         basegfx::B2DPolyPolygon(aNewPoly),
     180      656841 :                         rEntries[a].maBColor));
     181      218947 :             }
     182             : 
     183        1765 :             return aRetval;
     184             :         }
     185             : 
     186           0 :         Primitive2DSequence FillGradientPrimitive2D::createNonOverlappingFill(
     187             :             const std::vector< drawinglayer::texture::B2DHomMatrixAndBColor >& rEntries,
     188             :             const basegfx::BColor& rOuterColor,
     189             :             const basegfx::B2DPolygon& rUnitPolygon) const
     190             :         {
     191             :             // prepare return value
     192           0 :             Primitive2DSequence aRetval(rEntries.size() + 1);
     193             : 
     194             :             // get outmost viusible range from object
     195           0 :             basegfx::B2DRange aOutmostRange(getOutputRange());
     196           0 :             basegfx::B2DPolyPolygon aCombinedPolyPoly;
     197             : 
     198           0 :             if(rEntries.size())
     199             :             {
     200             :                 // extend aOutmostRange with first polygon
     201           0 :                 basegfx::B2DPolygon aFirstPoly(rUnitPolygon);
     202             : 
     203           0 :                 aFirstPoly.transform(rEntries[0].maB2DHomMatrix);
     204           0 :                 aCombinedPolyPoly.append(aFirstPoly);
     205           0 :                 aOutmostRange.expand(aFirstPoly.getB2DRange());
     206             :             }
     207             : 
     208             :             // add outmost range to combined polypolygon (in 1st place), create first primitive
     209           0 :             aCombinedPolyPoly.insert(0, basegfx::tools::createPolygonFromRect(aOutmostRange));
     210           0 :             aRetval[0] = Primitive2DReference(
     211             :                 new PolyPolygonColorPrimitive2D(
     212             :                     aCombinedPolyPoly,
     213           0 :                     rOuterColor));
     214             : 
     215           0 :             if(rEntries.size())
     216             :             {
     217             :                 // reuse first polygon, it's the second one
     218           0 :                 aCombinedPolyPoly.remove(0);
     219             : 
     220           0 :                 for(sal_uInt32 a(0); a < rEntries.size() - 1; a++)
     221             :                 {
     222             :                     // create next inner polygon, combinbe with last one
     223           0 :                     basegfx::B2DPolygon aNextPoly(rUnitPolygon);
     224             : 
     225           0 :                     aNextPoly.transform(rEntries[a + 1].maB2DHomMatrix);
     226           0 :                     aCombinedPolyPoly.append(aNextPoly);
     227             : 
     228             :                     // create primitive with correct color
     229           0 :                     aRetval[a + 1] = Primitive2DReference(
     230             :                         new PolyPolygonColorPrimitive2D(
     231             :                             aCombinedPolyPoly,
     232           0 :                             rEntries[a].maBColor));
     233             : 
     234             :                     // reuse inner polygon, it's the 2nd one
     235           0 :                     aCombinedPolyPoly.remove(0);
     236           0 :                 }
     237             : 
     238             :                 // add last inner polygon with last color
     239           0 :                 aRetval[rEntries.size()] = Primitive2DReference(
     240             :                     new PolyPolygonColorPrimitive2D(
     241             :                         aCombinedPolyPoly,
     242           0 :                         rEntries[rEntries.size() - 1].maBColor));
     243             :             }
     244             : 
     245           0 :             return aRetval;
     246             :         }
     247             : 
     248        1765 :         Primitive2DSequence FillGradientPrimitive2D::createFill(bool bOverlapping) const
     249             :         {
     250             :             // prepare shape of the Unit Polygon
     251        1765 :             basegfx::B2DPolygon aUnitPolygon;
     252             : 
     253        1765 :             switch(getFillGradient().getStyle())
     254             :             {
     255             :                 case attribute::GRADIENTSTYLE_RADIAL:
     256             :                 case attribute::GRADIENTSTYLE_ELLIPTICAL:
     257             :                 {
     258           0 :                     aUnitPolygon = basegfx::tools::createPolygonFromCircle(basegfx::B2DPoint(0.0, 0.0), 1.0);
     259           0 :                     break;
     260             :                 }
     261             :                 default: // GRADIENTSTYLE_LINEAR, attribute::GRADIENTSTYLE_AXIAL, attribute::GRADIENTSTYLE_SQUARE, attribute::GRADIENTSTYLE_RECT
     262             :                 {
     263        1765 :                     aUnitPolygon = basegfx::tools::createPolygonFromRect(basegfx::B2DRange(-1.0, -1.0, 1.0, 1.0));
     264        1765 :                     break;
     265             :                 }
     266             :             }
     267             : 
     268             :             // get the transform matrices and colors (where colors
     269             :             // will have one more entry that matrices)
     270        1765 :             std::vector< drawinglayer::texture::B2DHomMatrixAndBColor > aEntries;
     271        3530 :             basegfx::BColor aOuterColor;
     272             : 
     273        1765 :             generateMatricesAndColors(aEntries, aOuterColor);
     274             : 
     275        1765 :             if(bOverlapping)
     276             :             {
     277        1765 :                 return createOverlappingFill(aEntries, aOuterColor, aUnitPolygon);
     278             :             }
     279             :             else
     280             :             {
     281           0 :                 return createNonOverlappingFill(aEntries, aOuterColor, aUnitPolygon);
     282        1765 :             }
     283             :         }
     284             : 
     285        1765 :         Primitive2DSequence FillGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
     286             :         {
     287             :             // default creates overlapping fill which works with AntiAliasing and without.
     288             :             // The non-overlapping version does not create single filled polygons, but
     289             :             // PolyPolygons where each one describes a 'ring' for the gradient such
     290             :             // that the rings will not overlap. This is useful fir the old XOR-paint
     291             :             // 'trick' of VCL which is recorded in Metafiles; so this version may be
     292             :             // used from the MetafilePrimitive2D in it's decomposition.
     293             : 
     294        1765 :             if(!getFillGradient().isDefault())
     295             :             {
     296             :                 static bool bOverlapping(true); // allow to test non-overlapping in the debugger
     297             : 
     298        1765 :                 return createFill(bOverlapping);
     299             :             }
     300             :             else
     301             :             {
     302           0 :                 return Primitive2DSequence();
     303             :             }
     304             :         }
     305             : 
     306         504 :         FillGradientPrimitive2D::FillGradientPrimitive2D(
     307             :             const basegfx::B2DRange& rOutputRange,
     308             :             const attribute::FillGradientAttribute& rFillGradient)
     309             :         :   BufferedDecompositionPrimitive2D(),
     310             :             maOutputRange(rOutputRange),
     311             :             maDefinitionRange(rOutputRange),
     312         504 :             maFillGradient(rFillGradient)
     313             :         {
     314         504 :         }
     315             : 
     316        3303 :         FillGradientPrimitive2D::FillGradientPrimitive2D(
     317             :             const basegfx::B2DRange& rOutputRange,
     318             :             const basegfx::B2DRange& rDefinitionRange,
     319             :             const attribute::FillGradientAttribute& rFillGradient)
     320             :         :   BufferedDecompositionPrimitive2D(),
     321             :             maOutputRange(rOutputRange),
     322             :             maDefinitionRange(rDefinitionRange),
     323        3303 :             maFillGradient(rFillGradient)
     324             :         {
     325        3303 :         }
     326             : 
     327           0 :         bool FillGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
     328             :         {
     329           0 :             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
     330             :             {
     331           0 :                 const FillGradientPrimitive2D& rCompare = static_cast<const FillGradientPrimitive2D&>(rPrimitive);
     332             : 
     333           0 :                 return (getOutputRange() == rCompare.getOutputRange()
     334           0 :                     && getDefinitionRange() == rCompare.getDefinitionRange()
     335           0 :                     && getFillGradient() == rCompare.getFillGradient());
     336             :             }
     337             : 
     338           0 :             return false;
     339             :         }
     340             : 
     341         504 :         basegfx::B2DRange FillGradientPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
     342             :         {
     343             :             // return the geometrically visible area
     344         504 :             return getOutputRange();
     345             :         }
     346             : 
     347             :         // provide unique ID
     348        1775 :         ImplPrimitive2DIDBlock(FillGradientPrimitive2D, PRIMITIVE2D_ID_FILLGRADIENTPRIMITIVE2D)
     349             : 
     350             :     } // end of namespace primitive2d
     351             : } // end of namespace drawinglayer
     352             : 
     353             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11