2007-03-06 11:36:13 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
|
|
*
|
|
|
|
* $RCSfile: vclhelpergradient.cxx,v $
|
|
|
|
*
|
2008-05-27 13:11:34 +00:00
|
|
|
* $Revision: 1.5 $
|
2007-03-06 11:36:13 +00:00
|
|
|
*
|
2008-05-27 13:11:34 +00:00
|
|
|
* last change: $Author: aw $ $Date: 2008-05-27 14:11:22 $
|
2007-03-06 11:36:13 +00:00
|
|
|
*
|
|
|
|
* The Contents of this file are made available subject to
|
|
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* GNU Lesser General Public License Version 2.1
|
|
|
|
* =============================================
|
|
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
2008-03-05 08:18:45 +00:00
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
|
|
#include "precompiled_drawinglayer.hxx"
|
|
|
|
|
2007-03-06 11:36:13 +00:00
|
|
|
#include <vclhelpergradient.hxx>
|
|
|
|
#include <basegfx/range/b2drange.hxx>
|
|
|
|
#include <vcl/outdev.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
|
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
|
|
#include <drawinglayer/texture/texture.hxx>
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// support methods for vcl direct gradient renderering
|
|
|
|
|
|
|
|
namespace drawinglayer
|
|
|
|
{
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
sal_uInt32 impCalcGradientSteps(OutputDevice& rOutDev, sal_uInt32 nSteps, const basegfx::B2DRange& rRange, sal_uInt32 nMaxDist)
|
|
|
|
{
|
|
|
|
if(nSteps == 0L)
|
|
|
|
{
|
|
|
|
const Size aSize(rOutDev.LogicToPixel(Size(basegfx::fround(rRange.getWidth()), basegfx::fround(rRange.getHeight()))));
|
|
|
|
nSteps = (aSize.getWidth() + aSize.getHeight()) >> 3L;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(nSteps < 2L)
|
|
|
|
{
|
|
|
|
nSteps = 2L;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(nSteps > nMaxDist)
|
|
|
|
{
|
|
|
|
nSteps = nMaxDist;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nSteps;
|
|
|
|
}
|
|
|
|
|
|
|
|
void impDrawGradientToOutDevSimple(
|
|
|
|
OutputDevice& rOutDev,
|
|
|
|
const basegfx::B2DPolyPolygon& rTargetForm,
|
|
|
|
const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
|
|
|
|
const ::std::vector< basegfx::BColor >& rColors,
|
|
|
|
const basegfx::B2DPolygon& rUnitPolygon)
|
|
|
|
{
|
|
|
|
rOutDev.SetLineColor();
|
|
|
|
|
|
|
|
for(sal_uInt32 a(0L); a < rColors.size(); a++)
|
|
|
|
{
|
|
|
|
// set correct color
|
|
|
|
const basegfx::BColor aFillColor(rColors[a]);
|
|
|
|
rOutDev.SetFillColor(Color(aFillColor));
|
|
|
|
|
|
|
|
if(a)
|
|
|
|
{
|
2008-10-17 08:40:10 +00:00
|
|
|
if(a - 1L < static_cast< sal_uInt32 >(rMatrices.size()))
|
2007-03-06 11:36:13 +00:00
|
|
|
{
|
|
|
|
basegfx::B2DPolygon aNewPoly(rUnitPolygon);
|
|
|
|
aNewPoly.transform(rMatrices[a - 1L]);
|
2007-04-17 09:02:28 +00:00
|
|
|
rOutDev.DrawPolygon(aNewPoly);
|
2007-03-06 11:36:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-04-17 09:02:28 +00:00
|
|
|
rOutDev.DrawPolyPolygon(rTargetForm);
|
2007-03-06 11:36:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void impDrawGradientToOutDevComplex(
|
|
|
|
OutputDevice& rOutDev,
|
|
|
|
const basegfx::B2DPolyPolygon& rTargetForm,
|
|
|
|
const ::std::vector< basegfx::B2DHomMatrix >& rMatrices,
|
|
|
|
const ::std::vector< basegfx::BColor >& rColors,
|
|
|
|
const basegfx::B2DPolygon& rUnitPolygon)
|
|
|
|
{
|
|
|
|
PolyPolygon aVclTargetForm(rTargetForm);
|
|
|
|
::std::vector< Polygon > aVclPolygons;
|
|
|
|
sal_uInt32 a;
|
|
|
|
|
|
|
|
// remember and set to XOR
|
|
|
|
rOutDev.SetLineColor();
|
|
|
|
rOutDev.Push(PUSH_RASTEROP);
|
|
|
|
rOutDev.SetRasterOp(ROP_XOR);
|
|
|
|
|
|
|
|
// draw gradient PolyPolygons
|
|
|
|
for(a = 0L; a < rMatrices.size(); a++)
|
|
|
|
{
|
|
|
|
// create polygon and remember
|
|
|
|
basegfx::B2DPolygon aNewPoly(rUnitPolygon);
|
|
|
|
aNewPoly.transform(rMatrices[a]);
|
|
|
|
aVclPolygons.push_back(Polygon(aNewPoly));
|
|
|
|
|
|
|
|
// set correct color
|
|
|
|
if(rColors.size() > a)
|
|
|
|
{
|
|
|
|
const basegfx::BColor aFillColor(rColors[a]);
|
|
|
|
rOutDev.SetFillColor(Color(aFillColor));
|
|
|
|
}
|
|
|
|
|
|
|
|
// create vcl PolyPolygon and draw it
|
|
|
|
if(a)
|
|
|
|
{
|
|
|
|
PolyPolygon aVclPolyPoly(aVclPolygons[a - 1L]);
|
|
|
|
aVclPolyPoly.Insert(aVclPolygons[a]);
|
|
|
|
rOutDev.DrawPolyPolygon(aVclPolyPoly);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PolyPolygon aVclPolyPoly(aVclTargetForm);
|
|
|
|
aVclPolyPoly.Insert(aVclPolygons[0L]);
|
|
|
|
rOutDev.DrawPolyPolygon(aVclPolyPoly);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw last poly in last color
|
|
|
|
if(rColors.size())
|
|
|
|
{
|
|
|
|
const basegfx::BColor aFillColor(rColors[rColors.size() - 1L]);
|
|
|
|
rOutDev.SetFillColor(Color(aFillColor));
|
|
|
|
rOutDev.DrawPolygon(aVclPolygons[aVclPolygons.size() - 1L]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw object form in black and go back to XOR
|
|
|
|
rOutDev.SetFillColor(COL_BLACK);
|
|
|
|
rOutDev.SetRasterOp(ROP_0);
|
|
|
|
rOutDev.DrawPolyPolygon(aVclTargetForm);
|
|
|
|
rOutDev.SetRasterOp(ROP_XOR);
|
|
|
|
|
|
|
|
// draw gradient PolyPolygons again
|
|
|
|
for(a = 0L; a < rMatrices.size(); a++)
|
|
|
|
{
|
|
|
|
// set correct color
|
|
|
|
if(rColors.size() > a)
|
|
|
|
{
|
|
|
|
const basegfx::BColor aFillColor(rColors[a]);
|
|
|
|
rOutDev.SetFillColor(Color(aFillColor));
|
|
|
|
}
|
|
|
|
|
|
|
|
// create vcl PolyPolygon and draw it
|
|
|
|
if(a)
|
|
|
|
{
|
|
|
|
PolyPolygon aVclPolyPoly(aVclPolygons[a - 1L]);
|
|
|
|
aVclPolyPoly.Insert(aVclPolygons[a]);
|
|
|
|
rOutDev.DrawPolyPolygon(aVclPolyPoly);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PolyPolygon aVclPolyPoly(aVclTargetForm);
|
|
|
|
aVclPolyPoly.Insert(aVclPolygons[0L]);
|
|
|
|
rOutDev.DrawPolyPolygon(aVclPolyPoly);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw last poly in last color
|
|
|
|
if(rColors.size())
|
|
|
|
{
|
|
|
|
const basegfx::BColor aFillColor(rColors[rColors.size() - 1L]);
|
|
|
|
rOutDev.SetFillColor(Color(aFillColor));
|
|
|
|
rOutDev.DrawPolygon(aVclPolygons[aVclPolygons.size() - 1L]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// reset drawmode
|
|
|
|
rOutDev.Pop();
|
|
|
|
}
|
|
|
|
} // end of anonymous namespace
|
|
|
|
} // end of namespace drawinglayer
|
|
|
|
|
|
|
|
namespace drawinglayer
|
|
|
|
{
|
|
|
|
void impDrawGradientToOutDev(
|
|
|
|
OutputDevice& rOutDev,
|
|
|
|
const basegfx::B2DPolyPolygon& rTargetForm,
|
|
|
|
attribute::GradientStyle eGradientStyle,
|
|
|
|
sal_uInt32 nSteps,
|
|
|
|
const basegfx::BColor& rStart,
|
|
|
|
const basegfx::BColor& rEnd,
|
|
|
|
double fBorder, double fAngle, double fOffsetX, double fOffsetY, bool bSimple)
|
|
|
|
{
|
|
|
|
const basegfx::B2DRange aOutlineRange(basegfx::tools::getRange(rTargetForm));
|
|
|
|
::std::vector< basegfx::B2DHomMatrix > aMatrices;
|
|
|
|
::std::vector< basegfx::BColor > aColors;
|
|
|
|
basegfx::B2DPolygon aUnitPolygon;
|
|
|
|
|
|
|
|
if(attribute::GRADIENTSTYLE_RADIAL == eGradientStyle || attribute::GRADIENTSTYLE_ELLIPTICAL == eGradientStyle)
|
|
|
|
{
|
|
|
|
const basegfx::B2DPoint aCircleCenter(0.5, 0.5);
|
|
|
|
aUnitPolygon = basegfx::tools::createPolygonFromEllipse(aCircleCenter, 0.5, 0.5);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aUnitPolygon = basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure steps is not too high/low
|
|
|
|
nSteps = impCalcGradientSteps(rOutDev, nSteps, aOutlineRange, sal_uInt32((rStart.getMaximumDistance(rEnd) * 127.5) + 0.5));
|
|
|
|
|
|
|
|
// create geometries
|
|
|
|
switch(eGradientStyle)
|
|
|
|
{
|
|
|
|
case attribute::GRADIENTSTYLE_LINEAR:
|
|
|
|
{
|
|
|
|
texture::GeoTexSvxGradientLinear aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
|
|
|
|
aGradient.appendTransformations(aMatrices);
|
|
|
|
aGradient.appendColors(aColors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case attribute::GRADIENTSTYLE_AXIAL:
|
|
|
|
{
|
|
|
|
texture::GeoTexSvxGradientAxial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fAngle);
|
|
|
|
aGradient.appendTransformations(aMatrices);
|
|
|
|
aGradient.appendColors(aColors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case attribute::GRADIENTSTYLE_RADIAL:
|
|
|
|
{
|
|
|
|
texture::GeoTexSvxGradientRadial aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetY);
|
|
|
|
aGradient.appendTransformations(aMatrices);
|
|
|
|
aGradient.appendColors(aColors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case attribute::GRADIENTSTYLE_ELLIPTICAL:
|
|
|
|
{
|
|
|
|
texture::GeoTexSvxGradientElliptical aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
|
|
|
|
aGradient.appendTransformations(aMatrices);
|
|
|
|
aGradient.appendColors(aColors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case attribute::GRADIENTSTYLE_SQUARE:
|
|
|
|
{
|
|
|
|
texture::GeoTexSvxGradientSquare aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
|
|
|
|
aGradient.appendTransformations(aMatrices);
|
|
|
|
aGradient.appendColors(aColors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case attribute::GRADIENTSTYLE_RECT:
|
|
|
|
{
|
|
|
|
texture::GeoTexSvxGradientRect aGradient(aOutlineRange, rStart, rEnd, nSteps, fBorder, fOffsetX, fOffsetX, fAngle);
|
|
|
|
aGradient.appendTransformations(aMatrices);
|
|
|
|
aGradient.appendColors(aColors);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// paint them with mask using the XOR method
|
|
|
|
if(aMatrices.size())
|
|
|
|
{
|
|
|
|
if(bSimple)
|
|
|
|
{
|
|
|
|
impDrawGradientToOutDevSimple(rOutDev, rTargetForm, aMatrices, aColors, aUnitPolygon);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
impDrawGradientToOutDevComplex(rOutDev, rTargetForm, aMatrices, aColors, aUnitPolygon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // end of namespace drawinglayer
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// eof
|