1716 lines
72 KiB
C++
1716 lines
72 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: vclprocessor2d.cxx,v $
|
|
*
|
|
* $Revision: 1.4 $
|
|
*
|
|
* last change: $Author: aw $ $Date: 2007-01-25 18:21:36 $
|
|
*
|
|
* 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
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_VCLPROCESSOR2D_HXX
|
|
#include <drawinglayer/processor2d/vclprocessor2d.hxx>
|
|
#endif
|
|
|
|
#ifndef _SV_OUTDEV_HXX
|
|
#include <vcl/outdev.hxx>
|
|
#endif
|
|
|
|
#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX
|
|
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_FILLATTRIBUTE_HXX
|
|
#include <drawinglayer/attribute/fillattribute.hxx>
|
|
#endif
|
|
|
|
#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX
|
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
|
#endif
|
|
|
|
#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_TEXTURE_TEXTURE_HXX
|
|
#include <drawinglayer/texture/texture.hxx>
|
|
#endif
|
|
|
|
#ifndef _SV_BMPACC_HXX
|
|
#include <vcl/bmpacc.hxx>
|
|
#endif
|
|
|
|
#ifndef _SV_BITMAPEX_HXX
|
|
#include <vcl/bitmapex.hxx>
|
|
#endif
|
|
|
|
#ifndef _SV_VIRDEV_HXX
|
|
#include <vcl/virdev.hxx>
|
|
#endif
|
|
|
|
#ifndef _GRFMGR_HXX
|
|
#include <goodies/grfmgr.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE_TEXTPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYGONPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BITMAPPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_ATTRIBUTE_SDRFILLBITMAPATTRIBUTE_HXX
|
|
#include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_FILLBITMAPPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_POLYPOLYGONPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_METAFILEPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef _BGFX_TOOLS_CANVASTOOLS_HXX
|
|
#include <basegfx/tools/canvastools.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_MASKPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_ALPHAPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/alphaprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_TRANSFORMPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
|
|
#endif
|
|
|
|
#ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_MARKERARRAYPRIMITIVE2D_HXX
|
|
#include <drawinglayer/primitive2d/markerarrayprimitive2d.hxx>
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
using namespace com::sun::star;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// support methods for vcl direct gradeint 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)
|
|
{
|
|
if(a - 1L < rMatrices.size())
|
|
{
|
|
basegfx::B2DPolygon aNewPoly(rUnitPolygon);
|
|
aNewPoly.transform(rMatrices[a - 1L]);
|
|
rOutDev.DrawPolygon(Polygon(aNewPoly));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rOutDev.DrawPolyPolygon(PolyPolygon(rTargetForm));
|
|
}
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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);
|
|
// aUnitPolygon = basegfx::tools::adaptiveSubdivideByAngle(aUnitPolygon);
|
|
}
|
|
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 anonymous namespace
|
|
} // end of namespace drawinglayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// support for rendering Bitmap and BitmapEx contents
|
|
|
|
namespace drawinglayer
|
|
{
|
|
namespace
|
|
{
|
|
void impSmoothPoint(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
|
|
{
|
|
double fDeltaX(rSource.getX() - nIntX);
|
|
double fDeltaY(rSource.getY() - nIntY);
|
|
sal_Int32 nIndX(0L);
|
|
sal_Int32 nIndY(0L);
|
|
|
|
if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
|
|
{
|
|
nIndX++;
|
|
}
|
|
else if(fDeltaX < 0.0 && nIntX >= 1L)
|
|
{
|
|
fDeltaX = -fDeltaX;
|
|
nIndX--;
|
|
}
|
|
|
|
if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
|
|
{
|
|
nIndY++;
|
|
}
|
|
else if(fDeltaY < 0.0 && nIntY >= 1L)
|
|
{
|
|
fDeltaY = -fDeltaY;
|
|
nIndY--;
|
|
}
|
|
|
|
if(nIndX || nIndY)
|
|
{
|
|
const double fColorToReal(1.0 / 255.0);
|
|
double fR(rValue.GetRed() * fColorToReal);
|
|
double fG(rValue.GetGreen() * fColorToReal);
|
|
double fB(rValue.GetBlue() * fColorToReal);
|
|
double fRBottom(0.0), fGBottom(0.0), fBBottom(0.0);
|
|
|
|
if(nIndX)
|
|
{
|
|
const double fMulA(fDeltaX * fColorToReal);
|
|
double fMulB(1.0 - fDeltaX);
|
|
const BitmapColor aTopPartner(rRead.GetColor(nIntY, nIntX + nIndX));
|
|
|
|
fR = (fR * fMulB) + (aTopPartner.GetRed() * fMulA);
|
|
fG = (fG * fMulB) + (aTopPartner.GetGreen() * fMulA);
|
|
fB = (fB * fMulB) + (aTopPartner.GetBlue() * fMulA);
|
|
|
|
if(nIndY)
|
|
{
|
|
fMulB *= fColorToReal;
|
|
const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
|
|
const BitmapColor aBottomPartner(rRead.GetColor(nIntY + nIndY, nIntX + nIndX));
|
|
|
|
fRBottom = (aBottom.GetRed() * fMulB) + (aBottomPartner.GetRed() * fMulA);
|
|
fGBottom = (aBottom.GetGreen() * fMulB) + (aBottomPartner.GetGreen() * fMulA);
|
|
fBBottom = (aBottom.GetBlue() * fMulB) + (aBottomPartner.GetBlue() * fMulA);
|
|
}
|
|
}
|
|
|
|
if(nIndY)
|
|
{
|
|
if(!nIndX)
|
|
{
|
|
const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
|
|
|
|
fRBottom = aBottom.GetRed() * fColorToReal;
|
|
fGBottom = aBottom.GetGreen() * fColorToReal;
|
|
fBBottom = aBottom.GetBlue() * fColorToReal;
|
|
}
|
|
|
|
const double fMulB(1.0 - fDeltaY);
|
|
|
|
fR = (fR * fMulB) + (fRBottom * fDeltaY);
|
|
fG = (fG * fMulB) + (fGBottom * fDeltaY);
|
|
fB = (fB * fMulB) + (fBBottom * fDeltaY);
|
|
}
|
|
|
|
rValue.SetRed((sal_uInt8)(fR * 255.0));
|
|
rValue.SetGreen((sal_uInt8)(fG * 255.0));
|
|
rValue.SetBlue((sal_uInt8)(fB * 255.0));
|
|
}
|
|
}
|
|
|
|
void impSmoothIndex(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
|
|
{
|
|
double fDeltaX(rSource.getX() - nIntX);
|
|
double fDeltaY(rSource.getY() - nIntY);
|
|
sal_Int32 nIndX(0L);
|
|
sal_Int32 nIndY(0L);
|
|
|
|
if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
|
|
{
|
|
nIndX++;
|
|
}
|
|
else if(fDeltaX < 0.0 && nIntX >= 1L)
|
|
{
|
|
fDeltaX = -fDeltaX;
|
|
nIndX--;
|
|
}
|
|
|
|
if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
|
|
{
|
|
nIndY++;
|
|
}
|
|
else if(fDeltaY < 0.0 && nIntY >= 1L)
|
|
{
|
|
fDeltaY = -fDeltaY;
|
|
nIndY--;
|
|
}
|
|
|
|
if(nIndX || nIndY)
|
|
{
|
|
const double fColorToReal(1.0 / 255.0);
|
|
double fVal(rValue.GetIndex() * fColorToReal);
|
|
double fValBottom(0.0);
|
|
|
|
if(nIndX)
|
|
{
|
|
const double fMulA(fDeltaX * fColorToReal);
|
|
double fMulB(1.0 - fDeltaX);
|
|
const BitmapColor aTopPartner(rRead.GetPixel(nIntY, nIntX + nIndX));
|
|
|
|
fVal = (fVal * fMulB) + (aTopPartner.GetIndex() * fMulA);
|
|
|
|
if(nIndY)
|
|
{
|
|
fMulB *= fColorToReal;
|
|
const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX));
|
|
const BitmapColor aBottomPartner(rRead.GetPixel(nIntY + nIndY, nIntX + nIndX));
|
|
|
|
fValBottom = (aBottom.GetIndex() * fMulB) + (aBottomPartner.GetIndex() * fMulA);
|
|
}
|
|
}
|
|
|
|
if(nIndY)
|
|
{
|
|
if(!nIndX)
|
|
{
|
|
const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX));
|
|
|
|
fValBottom = aBottom.GetIndex() * fColorToReal;
|
|
}
|
|
|
|
const double fMulB(1.0 - fDeltaY);
|
|
|
|
fVal = (fVal * fMulB) + (fValBottom * fDeltaY);
|
|
}
|
|
|
|
rValue.SetIndex((sal_uInt8)(fVal * 255.0));
|
|
}
|
|
}
|
|
|
|
void impTransformBitmap(const Bitmap& rSource, Bitmap& rDestination, const basegfx::B2DHomMatrix& rTransform, bool bSmooth)
|
|
{
|
|
BitmapWriteAccess* pWrite = rDestination.AcquireWriteAccess();
|
|
|
|
if(pWrite)
|
|
{
|
|
const Size aContentSizePixel(rSource.GetSizePixel());
|
|
BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
|
|
|
|
if(pRead)
|
|
{
|
|
const Size aDestinationSizePixel(rDestination.GetSizePixel());
|
|
bool bWorkWithIndex(rDestination.GetBitCount() <= 8);
|
|
BitmapColor aOutside(pRead->GetBestMatchingColor(BitmapColor(0xff, 0xff, 0xff)));
|
|
|
|
for(sal_Int32 y(0L); y < aDestinationSizePixel.getHeight(); y++)
|
|
{
|
|
for(sal_Int32 x(0L); x < aDestinationSizePixel.getWidth(); x++)
|
|
{
|
|
const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
|
|
const sal_Int32 nIntX(basegfx::fround(aSourceCoor.getX()));
|
|
|
|
if(nIntX >= 0L && nIntX < aContentSizePixel.getWidth())
|
|
{
|
|
const sal_Int32 nIntY(basegfx::fround(aSourceCoor.getY()));
|
|
|
|
if(nIntY >= 0L && nIntY < aContentSizePixel.getHeight())
|
|
{
|
|
if(bWorkWithIndex)
|
|
{
|
|
BitmapColor aValue(pRead->GetPixel(nIntY, nIntX));
|
|
|
|
if(bSmooth)
|
|
{
|
|
impSmoothIndex(aValue, aSourceCoor, nIntX, nIntY, *pRead);
|
|
}
|
|
|
|
pWrite->SetPixel(y, x, aValue);
|
|
}
|
|
else
|
|
{
|
|
BitmapColor aValue(pRead->GetColor(nIntY, nIntX));
|
|
|
|
if(bSmooth)
|
|
{
|
|
impSmoothPoint(aValue, aSourceCoor, nIntX, nIntY, *pRead);
|
|
}
|
|
|
|
pWrite->SetPixel(y, x, aValue.IsIndex() ? aValue : pWrite->GetBestMatchingColor(aValue));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// here are outside pixels. Complete mask
|
|
if(bWorkWithIndex)
|
|
{
|
|
pWrite->SetPixel(y, x, aOutside);
|
|
}
|
|
}
|
|
}
|
|
|
|
delete pRead;
|
|
}
|
|
|
|
delete pWrite;
|
|
}
|
|
}
|
|
|
|
Bitmap impCreateEmptyBitmapWithPattern(const Bitmap& rSource, const Size& aTargetSizePixel)
|
|
{
|
|
Bitmap aRetval;
|
|
BitmapReadAccess* pReadAccess = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
|
|
|
|
if(pReadAccess)
|
|
{
|
|
if(rSource.GetBitCount() <= 8)
|
|
{
|
|
BitmapPalette aPalette(pReadAccess->GetPalette());
|
|
aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount(), &aPalette);
|
|
}
|
|
else
|
|
{
|
|
aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount());
|
|
}
|
|
|
|
delete pReadAccess;
|
|
}
|
|
|
|
return aRetval;
|
|
}
|
|
|
|
BitmapEx impTransformBitmapEx(const BitmapEx& rSource, const Rectangle &rCroppedRectPixel, const basegfx::B2DHomMatrix& rTransform)
|
|
{
|
|
// force destination to 24 bit, we want to smooth output
|
|
const Size aDestinationSize(rCroppedRectPixel.GetSize());
|
|
Bitmap aDestination(impCreateEmptyBitmapWithPattern(rSource.GetBitmap(), aDestinationSize));
|
|
static bool bDoSmoothAtAll(true);
|
|
impTransformBitmap(rSource.GetBitmap(), aDestination, rTransform, bDoSmoothAtAll);
|
|
|
|
// create mask
|
|
if(rSource.IsTransparent())
|
|
{
|
|
if(rSource.IsAlpha())
|
|
{
|
|
Bitmap aAlpha(impCreateEmptyBitmapWithPattern(rSource.GetAlpha().GetBitmap(), aDestinationSize));
|
|
impTransformBitmap(rSource.GetAlpha().GetBitmap(), aAlpha, rTransform, bDoSmoothAtAll);
|
|
return BitmapEx(aDestination, AlphaMask(aAlpha));
|
|
}
|
|
else
|
|
{
|
|
Bitmap aMask(impCreateEmptyBitmapWithPattern(rSource.GetMask(), aDestinationSize));
|
|
impTransformBitmap(rSource.GetMask(), aMask, rTransform, false);
|
|
return BitmapEx(aDestination, aMask);
|
|
}
|
|
}
|
|
|
|
return BitmapEx(aDestination);
|
|
}
|
|
|
|
} // end of anonymous namespace
|
|
} // end of namespace drawinglayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// support class for OutputDevice output with mask
|
|
|
|
namespace drawinglayer
|
|
{
|
|
namespace
|
|
{
|
|
class impBufferDevice
|
|
{
|
|
OutputDevice& mrOutDev;
|
|
VirtualDevice maContent;
|
|
VirtualDevice* mpMask;
|
|
VirtualDevice* mpAlpha;
|
|
Rectangle maDestPixel;
|
|
|
|
public:
|
|
impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange);
|
|
~impBufferDevice();
|
|
|
|
void paint(double fTrans = 0.0);
|
|
bool isVisible() const { return !maDestPixel.IsEmpty(); }
|
|
VirtualDevice& getContent() { return maContent; }
|
|
VirtualDevice& getMask();
|
|
VirtualDevice& getAlpha();
|
|
};
|
|
|
|
impBufferDevice::impBufferDevice(OutputDevice& rOutDev, const basegfx::B2DRange& rRange)
|
|
: mrOutDev(rOutDev),
|
|
maContent(rOutDev),
|
|
mpMask(0L),
|
|
mpAlpha(0L)
|
|
{
|
|
const Rectangle aRectLogic(
|
|
(sal_Int32)floor(rRange.getMinX()), (sal_Int32)floor(rRange.getMinY()),
|
|
(sal_Int32)floor(rRange.getMaxX()) + 1L, (sal_Int32)floor(rRange.getMaxY()) + 1L);
|
|
const Rectangle aRectPixel(rOutDev.LogicToPixel(aRectLogic));
|
|
const Point aEmptyPoint;
|
|
maDestPixel = Rectangle(aEmptyPoint, rOutDev.GetOutputSizePixel());
|
|
maDestPixel.Intersection(aRectPixel);
|
|
|
|
if(isVisible())
|
|
{
|
|
maContent.SetOutputSizePixel(maDestPixel.GetSize(), false);
|
|
|
|
const bool bWasEnabledSrc(rOutDev.IsMapModeEnabled());
|
|
rOutDev.EnableMapMode(false);
|
|
maContent.DrawOutDev(aEmptyPoint, maDestPixel.GetSize(), maDestPixel.TopLeft(), maDestPixel.GetSize(), rOutDev);
|
|
rOutDev.EnableMapMode(bWasEnabledSrc);
|
|
|
|
MapMode aNewMapMode(rOutDev.GetMapMode());
|
|
const Point aLogicTopLeft(rOutDev.PixelToLogic(maDestPixel.TopLeft()));
|
|
aNewMapMode.SetOrigin(Point(-aLogicTopLeft.X(), -aLogicTopLeft.Y()));
|
|
|
|
maContent.SetMapMode(aNewMapMode);
|
|
}
|
|
}
|
|
|
|
impBufferDevice::~impBufferDevice()
|
|
{
|
|
delete mpMask;
|
|
delete mpAlpha;
|
|
}
|
|
|
|
void impBufferDevice::paint(double fTrans)
|
|
{
|
|
const Point aEmptyPoint;
|
|
const Size aSizePixel(maContent.GetOutputSizePixel());
|
|
const bool bWasEnabledDst(mrOutDev.IsMapModeEnabled());
|
|
|
|
mrOutDev.EnableMapMode(false);
|
|
maContent.EnableMapMode(false);
|
|
Bitmap aContent(maContent.GetBitmap(aEmptyPoint, aSizePixel));
|
|
|
|
if(mpAlpha)
|
|
{
|
|
mpAlpha->EnableMapMode(false);
|
|
AlphaMask aAlphaMask(mpAlpha->GetBitmap(aEmptyPoint, aSizePixel));
|
|
mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
|
|
}
|
|
else if(mpMask)
|
|
{
|
|
mpMask->EnableMapMode(false);
|
|
Bitmap aMask(mpMask->GetBitmap(aEmptyPoint, aSizePixel));
|
|
mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aMask));
|
|
}
|
|
else if(0.0 != fTrans)
|
|
{
|
|
sal_uInt8 nMaskValue((sal_uInt8)basegfx::fround(fTrans * 255.0));
|
|
AlphaMask aAlphaMask(aSizePixel, &nMaskValue);
|
|
mrOutDev.DrawBitmapEx(maDestPixel.TopLeft(), BitmapEx(aContent, aAlphaMask));
|
|
}
|
|
else
|
|
{
|
|
mrOutDev.DrawBitmap(maDestPixel.TopLeft(), aContent);
|
|
}
|
|
|
|
mrOutDev.EnableMapMode(bWasEnabledDst);
|
|
}
|
|
|
|
VirtualDevice& impBufferDevice::getMask()
|
|
{
|
|
if(!mpMask)
|
|
{
|
|
mpMask = new VirtualDevice(mrOutDev, 1);
|
|
mpMask->SetOutputSizePixel(maDestPixel.GetSize(), true);
|
|
mpMask->SetMapMode(maContent.GetMapMode());
|
|
}
|
|
|
|
return *mpMask;
|
|
}
|
|
|
|
VirtualDevice& impBufferDevice::getAlpha()
|
|
{
|
|
if(!mpAlpha)
|
|
{
|
|
mpAlpha = new VirtualDevice();
|
|
mpAlpha->SetOutputSizePixel(maDestPixel.GetSize(), true);
|
|
mpAlpha->SetMapMode(maContent.GetMapMode());
|
|
}
|
|
|
|
return *mpAlpha;
|
|
}
|
|
} // end of anonymous namespace
|
|
} // end of namespace drawinglayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// support for different kinds of bitmap rendering using vcl
|
|
|
|
namespace drawinglayer
|
|
{
|
|
namespace
|
|
{
|
|
void RenderBitmapPrimitive2D_GraphicManager(OutputDevice& rOutDev, const BitmapEx& rBitmapEx, const basegfx::B2DHomMatrix& rTransform)
|
|
{
|
|
// prepare attributes
|
|
GraphicAttr aAttributes;
|
|
|
|
// decompose matrix to check for shear, rotate and mirroring
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
// mirror flags
|
|
aAttributes.SetMirrorFlags(
|
|
(basegfx::fTools::less(aScale.getX(), 0.0) ? BMP_MIRROR_HORZ : 0)|
|
|
(basegfx::fTools::less(aScale.getY(), 0.0) ? BMP_MIRROR_VERT : 0));
|
|
|
|
// rotation
|
|
if(!basegfx::fTools::equalZero(fRotate))
|
|
{
|
|
double fRotation(fmod(3600.0 - (fRotate * (10.0 / F_PI180)), 3600.0));
|
|
aAttributes.SetRotation((sal_uInt16)(fRotation));
|
|
}
|
|
|
|
// prepare Bitmap
|
|
basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
|
|
|
|
if(basegfx::fTools::equalZero(fRotate))
|
|
{
|
|
aOutlineRange.transform(rTransform);
|
|
}
|
|
else
|
|
{
|
|
// if rotated, create the unrotated output rectangle for the GraphicManager paint
|
|
basegfx::B2DHomMatrix aSimpleObjectMatrix;
|
|
|
|
aSimpleObjectMatrix.scale(fabs(aScale.getX()), fabs(aScale.getY()));
|
|
aSimpleObjectMatrix.translate(aTranslate.getX(), aTranslate.getY());
|
|
|
|
aOutlineRange.transform(aSimpleObjectMatrix);
|
|
}
|
|
|
|
// prepare dest coor
|
|
const Rectangle aDestRectPixel(
|
|
basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
|
|
basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
|
|
|
|
// paint it using GraphicManager
|
|
Graphic aGraphic(rBitmapEx);
|
|
GraphicObject aGraphicObject(aGraphic);
|
|
aGraphicObject.Draw(&rOutDev, aDestRectPixel.TopLeft(), aDestRectPixel.GetSize(), &aAttributes);
|
|
}
|
|
|
|
void RenderBitmapPrimitive2D_BitmapEx(OutputDevice& rOutDev, const BitmapEx& rBitmapEx, const basegfx::B2DHomMatrix& rTransform)
|
|
{
|
|
// only translate and scale, use vcl's DrawBitmapEx().
|
|
BitmapEx aContent(rBitmapEx);
|
|
|
|
// prepare dest coor. Necessary to expand since vcl's DrawBitmapEx draws one pix less
|
|
basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
|
|
aOutlineRange.transform(rTransform);
|
|
const Rectangle aDestRectPixel(
|
|
basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
|
|
basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
|
|
|
|
// decompose matrix to check for shear, rotate and mirroring
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
// Check mirroring.
|
|
sal_uInt32 nMirrorFlags(BMP_MIRROR_NONE);
|
|
|
|
if(basegfx::fTools::less(aScale.getX(), 0.0))
|
|
{
|
|
nMirrorFlags |= BMP_MIRROR_HORZ;
|
|
}
|
|
|
|
if(basegfx::fTools::less(aScale.getY(), 0.0))
|
|
{
|
|
nMirrorFlags |= BMP_MIRROR_VERT;
|
|
}
|
|
|
|
if(BMP_MIRROR_NONE != nMirrorFlags)
|
|
{
|
|
aContent.Mirror(nMirrorFlags);
|
|
}
|
|
|
|
// draw bitmap
|
|
rOutDev.DrawBitmapEx(aDestRectPixel.TopLeft(), aDestRectPixel.GetSize(), aContent);
|
|
}
|
|
|
|
void RenderBitmapPrimitive2D_self(OutputDevice& rOutDev, const BitmapEx& rBitmapEx, const basegfx::B2DHomMatrix& rTransform)
|
|
{
|
|
// process self with free transformation (containing shear and rotate). Get dest rect in pixels.
|
|
basegfx::B2DRange aOutlineRange(0.0, 0.0, 1.0, 1.0);
|
|
aOutlineRange.transform(rTransform);
|
|
const Rectangle aDestRectLogic(
|
|
basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
|
|
basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
|
|
const Rectangle aDestRectPixel(rOutDev.LogicToPixel(aDestRectLogic));
|
|
|
|
// intersect with output pixel size
|
|
const Rectangle aOutputRectPixel(Point(), rOutDev.GetOutputSizePixel());
|
|
const Rectangle aCroppedRectPixel(aDestRectPixel.GetIntersection(aOutputRectPixel));
|
|
|
|
if(!aCroppedRectPixel.IsEmpty())
|
|
{
|
|
// build transform from pixel in aDestination to pixel in rBitmapEx
|
|
basegfx::B2DHomMatrix aTransform;
|
|
|
|
// from relative in aCroppedRectPixel to relative in aDestRectPixel
|
|
aTransform.translate(aCroppedRectPixel.Left() - aDestRectPixel.Left(), aCroppedRectPixel.Top() - aDestRectPixel.Top());
|
|
|
|
// from relative in aDestRectPixel to absolute Logic
|
|
aTransform.scale((double)aDestRectLogic.getWidth() / (double)aDestRectPixel.getWidth(), (double)aDestRectLogic.getHeight() / (double)aDestRectPixel.getHeight());
|
|
aTransform.translate(aDestRectLogic.Left(), aDestRectLogic.Top());
|
|
|
|
// from absolute in Logic to unified object coordinates (0.0 .. 1.0 in x and y)
|
|
basegfx::B2DHomMatrix aInvBitmapTransform(rTransform);
|
|
aInvBitmapTransform.invert();
|
|
aTransform = aInvBitmapTransform * aTransform;
|
|
|
|
// from unit object coordinates to rBitmapEx pixel coordintes
|
|
const Size aSourceSizePixel(rBitmapEx.GetSizePixel());
|
|
aTransform.scale(aSourceSizePixel.getWidth() - 1L, aSourceSizePixel.getHeight() - 1L);
|
|
|
|
// create bitmap using source, destination and linear back-transformation
|
|
BitmapEx aDestination = impTransformBitmapEx(rBitmapEx, aCroppedRectPixel, aTransform);
|
|
|
|
// paint
|
|
const bool bWasEnabled(rOutDev.IsMapModeEnabled());
|
|
rOutDev.EnableMapMode(false);
|
|
rOutDev.DrawBitmapEx(aCroppedRectPixel.TopLeft(), aDestination);
|
|
rOutDev.EnableMapMode(bWasEnabled);
|
|
}
|
|
}
|
|
|
|
BitmapEx impModifyBitmapEx(const basegfx::BColorModifierStack& rBColorModifierStack, const BitmapEx& rSource)
|
|
{
|
|
Bitmap aChangedBitmap(rSource.GetBitmap());
|
|
bool bDone(false);
|
|
|
|
for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
|
|
{
|
|
const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
|
|
|
|
switch(rModifier.getMode())
|
|
{
|
|
case basegfx::BCOLORMODIFYMODE_REPLACE :
|
|
{
|
|
// complete replace
|
|
if(rSource.IsTransparent())
|
|
{
|
|
// clear bitmap with dest color
|
|
aChangedBitmap.Erase(Color(rModifier.getBColor()));
|
|
}
|
|
else
|
|
{
|
|
// erase bitmap, caller will know to paint direct
|
|
aChangedBitmap.SetEmpty();
|
|
}
|
|
|
|
bDone = true;
|
|
break;
|
|
}
|
|
|
|
default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
|
|
{
|
|
BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
|
|
|
|
if(pContent)
|
|
{
|
|
const double fConvertColor(1.0 / 255.0);
|
|
|
|
for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
|
|
{
|
|
for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
|
|
{
|
|
const BitmapColor aBMCol(pContent->GetColor(y, x));
|
|
const basegfx::BColor aBSource(
|
|
(double)aBMCol.GetRed() * fConvertColor,
|
|
(double)aBMCol.GetGreen() * fConvertColor,
|
|
(double)aBMCol.GetBlue() * fConvertColor);
|
|
const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource));
|
|
|
|
pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
|
|
}
|
|
}
|
|
|
|
delete pContent;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(aChangedBitmap.IsEmpty())
|
|
{
|
|
return BitmapEx();
|
|
}
|
|
else
|
|
{
|
|
if(rSource.IsTransparent())
|
|
{
|
|
if(rSource.IsAlpha())
|
|
{
|
|
return BitmapEx(aChangedBitmap, rSource.GetAlpha());
|
|
}
|
|
else
|
|
{
|
|
return BitmapEx(aChangedBitmap, rSource.GetMask());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return BitmapEx(aChangedBitmap);
|
|
}
|
|
}
|
|
}
|
|
} // end of anonymous namespace
|
|
} // end of namespace drawinglayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace drawinglayer
|
|
{
|
|
namespace processor2d
|
|
{
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// rendering support
|
|
|
|
// directdraw of text simple portion
|
|
void VclProcessor2D::RenderTextSimplePortionPrimitive2D(const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
|
|
{
|
|
// decompose matrix to have position and size of text
|
|
basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rTextCandidate.getTextTransform());
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
bool bPrimitiveAccepted(false);
|
|
|
|
if(basegfx::fTools::equalZero(fShearX))
|
|
{
|
|
if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
|
|
{
|
|
// handle special case: If scale is negative in (x,y) (3rd quadrant), it can
|
|
// be expressed as rotation by PI
|
|
aScale = basegfx::absolute(aScale);
|
|
fRotate += F_PI;
|
|
}
|
|
|
|
if(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0))
|
|
{
|
|
// handle, there is no shear and no mirror
|
|
bPrimitiveAccepted = true;
|
|
const Font aFont(primitive2d::getVclFontFromFontAttributes(rTextCandidate.getFontAttributes(), aScale, fRotate));
|
|
const basegfx::B2DPoint aPoint(aLocalTransform * basegfx::B2DPoint(0.0, 0.0));
|
|
const Point aStartPoint(basegfx::fround(aPoint.getX()), basegfx::fround(aPoint.getY()));
|
|
|
|
// create transformed integer DXArray in view coordinate system
|
|
::std::vector< sal_Int32 > aTransformedDXArray;
|
|
|
|
if(rTextCandidate.getDXArray().size())
|
|
{
|
|
aTransformedDXArray.reserve(rTextCandidate.getDXArray().size());
|
|
const basegfx::B2DVector aPixelVector(aLocalTransform * basegfx::B2DVector(1.0, 0.0));
|
|
const double fPixelVectorLength(aPixelVector.getLength());
|
|
|
|
for(::std::vector< double >::const_iterator aStart(rTextCandidate.getDXArray().begin()); aStart != rTextCandidate.getDXArray().end(); aStart++)
|
|
{
|
|
aTransformedDXArray.push_back(basegfx::fround((*aStart) * fPixelVectorLength));
|
|
}
|
|
}
|
|
|
|
// set parameters and paint
|
|
const basegfx::BColor aRGBFontColor(maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
|
|
mpOutputDevice->SetFont(aFont);
|
|
mpOutputDevice->SetTextColor(Color(aRGBFontColor));
|
|
mpOutputDevice->DrawTextArray(aStartPoint, rTextCandidate.getText(),
|
|
aTransformedDXArray.size() ? &(aTransformedDXArray[0]) : NULL);
|
|
}
|
|
}
|
|
|
|
if(!bPrimitiveAccepted)
|
|
{
|
|
// let break down
|
|
process(rTextCandidate.get2DDecomposition(getViewInformation2D()));
|
|
}
|
|
}
|
|
|
|
// direct draw of hairline
|
|
void VclProcessor2D::RenderPolygonHairlinePrimitive2D(const primitive2d::PolygonHairlinePrimitive2D& rPolygonCandidate)
|
|
{
|
|
const basegfx::BColor aHairlineColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
|
|
mpOutputDevice->SetLineColor(Color(aHairlineColor));
|
|
mpOutputDevice->SetFillColor();
|
|
|
|
basegfx::B2DPolygon aLocalPolygon(rPolygonCandidate.getB2DPolygon());
|
|
aLocalPolygon.transform(maCurrentTransformation);
|
|
|
|
mpOutputDevice->DrawPolyLine(Polygon(aLocalPolygon));
|
|
}
|
|
|
|
// direct draw of transformed BitmapEx primitive
|
|
void VclProcessor2D::RenderBitmapPrimitive2D(const primitive2d::BitmapPrimitive2D& rBitmapCandidate)
|
|
{
|
|
// create local transform
|
|
basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rBitmapCandidate.getTransform());
|
|
BitmapEx aBitmapEx(rBitmapCandidate.getBitmapEx());
|
|
bool bPainted(false);
|
|
|
|
if(maBColorModifierStack.count())
|
|
{
|
|
aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx);
|
|
|
|
if(aBitmapEx.IsEmpty())
|
|
{
|
|
// color gets completely replaced, get it
|
|
const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
|
|
basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
|
|
aPolygon.transform(aLocalTransform);
|
|
|
|
mpOutputDevice->SetFillColor(Color(aModifiedColor));
|
|
mpOutputDevice->SetLineColor();
|
|
mpOutputDevice->DrawPolygon(Polygon(aPolygon));
|
|
|
|
bPainted = true;
|
|
}
|
|
}
|
|
|
|
if(!bPainted)
|
|
{
|
|
static bool bForceUseOfOwnTransformer(false);
|
|
static bool bUseGraphicManager(true);
|
|
|
|
// decompose matrix to check for shear, rotate and mirroring
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
if(!bForceUseOfOwnTransformer && basegfx::fTools::equalZero(fShearX))
|
|
{
|
|
if(!bUseGraphicManager && basegfx::fTools::equalZero(fRotate))
|
|
{
|
|
RenderBitmapPrimitive2D_BitmapEx(*mpOutputDevice, aBitmapEx, aLocalTransform);
|
|
}
|
|
else
|
|
{
|
|
RenderBitmapPrimitive2D_GraphicManager(*mpOutputDevice, aBitmapEx, aLocalTransform);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!aBitmapEx.IsTransparent() && (!basegfx::fTools::equalZero(fShearX) || !basegfx::fTools::equalZero(fRotate)))
|
|
{
|
|
// parts will be uncovered, extend aBitmapEx with a mask bitmap
|
|
const Bitmap aContent(aBitmapEx.GetBitmap());
|
|
aBitmapEx = BitmapEx(aContent, Bitmap(aContent.GetSizePixel(), 1));
|
|
}
|
|
|
|
RenderBitmapPrimitive2D_self(*mpOutputDevice, aBitmapEx, aLocalTransform);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VclProcessor2D::RenderFillBitmapPrimitive2D(const primitive2d::FillBitmapPrimitive2D& rFillBitmapCandidate)
|
|
{
|
|
const attribute::FillBitmapAttribute& rFillBitmapAttribute(rFillBitmapCandidate.getFillBitmap());
|
|
bool bPrimitiveAccepted(false);
|
|
|
|
if(rFillBitmapAttribute.getTiling())
|
|
{
|
|
// decompose matrix to check for shear, rotate and mirroring
|
|
basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rFillBitmapCandidate.getTransformation());
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
if(basegfx::fTools::equalZero(fRotate) && basegfx::fTools::equalZero(fShearX))
|
|
{
|
|
// no shear or rotate, draw direct in pixel coordinates
|
|
bPrimitiveAccepted = true;
|
|
BitmapEx aBitmapEx(rFillBitmapAttribute.getBitmap());
|
|
bool bPainted(false);
|
|
|
|
if(maBColorModifierStack.count())
|
|
{
|
|
aBitmapEx = impModifyBitmapEx(maBColorModifierStack, aBitmapEx);
|
|
|
|
if(aBitmapEx.IsEmpty())
|
|
{
|
|
// color gets completely replaced, get it
|
|
const basegfx::BColor aModifiedColor(maBColorModifierStack.getModifiedColor(basegfx::BColor()));
|
|
basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(0.0, 0.0, 1.0, 1.0)));
|
|
aPolygon.transform(aLocalTransform);
|
|
|
|
mpOutputDevice->SetFillColor(Color(aModifiedColor));
|
|
mpOutputDevice->SetLineColor();
|
|
mpOutputDevice->DrawPolygon(Polygon(aPolygon));
|
|
|
|
bPainted = true;
|
|
}
|
|
}
|
|
|
|
if(!bPainted)
|
|
{
|
|
const basegfx::B2DPoint aObjTopLeft(aTranslate.getX(), aTranslate.getY());
|
|
const basegfx::B2DPoint aObjBottomRight(aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
|
|
const Point aObjTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjTopLeft.getX(), (sal_Int32)aObjTopLeft.getY())));
|
|
const Point aObjBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aObjBottomRight.getX(), (sal_Int32)aObjBottomRight.getY())));
|
|
|
|
const basegfx::B2DPoint aBmpTopLeft(aLocalTransform * rFillBitmapAttribute.getTopLeft());
|
|
const basegfx::B2DPoint aBmpBottomRight(aLocalTransform * basegfx::B2DPoint(rFillBitmapAttribute.getTopLeft() + rFillBitmapAttribute.getSize()));
|
|
const Point aBmpTL(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpTopLeft.getX(), (sal_Int32)aBmpTopLeft.getY())));
|
|
const Point aBmpBR(mpOutputDevice->LogicToPixel(Point((sal_Int32)aBmpBottomRight.getX(), (sal_Int32)aBmpBottomRight.getY())));
|
|
|
|
sal_Int32 nOWidth(aObjBR.X() - aObjTL.X());
|
|
sal_Int32 nOHeight(aObjBR.Y() - aObjTL.Y());
|
|
|
|
if(nOWidth < 0L)
|
|
{
|
|
nOWidth = 1L;
|
|
}
|
|
|
|
if(nOHeight < 0L)
|
|
{
|
|
nOHeight = 1L;
|
|
}
|
|
|
|
sal_Int32 nBWidth(aBmpBR.X() - aBmpTL.X());
|
|
sal_Int32 nBHeight(aBmpBR.Y() - aBmpTL.Y());
|
|
|
|
if(nBWidth < 0L)
|
|
{
|
|
nBWidth = 1L;
|
|
}
|
|
|
|
if(nBHeight < 0L)
|
|
{
|
|
nBHeight = 1L;
|
|
}
|
|
|
|
sal_Int32 nBLeft(aBmpTL.X());
|
|
sal_Int32 nBTop(aBmpTL.Y());
|
|
|
|
if(nBLeft > aObjTL.X())
|
|
{
|
|
nBLeft -= ((nBLeft / nBWidth) + 1L) * nBWidth;
|
|
}
|
|
|
|
if(nBLeft + nBWidth <= aObjTL.X())
|
|
{
|
|
nBLeft -= (nBLeft / nBWidth) * nBWidth;
|
|
}
|
|
|
|
if(nBTop > aObjTL.Y())
|
|
{
|
|
nBTop -= ((nBTop / nBHeight) + 1L) * nBHeight;
|
|
}
|
|
|
|
if(nBTop + nBHeight <= aObjTL.Y())
|
|
{
|
|
nBTop -= (nBTop / nBHeight) * nBHeight;
|
|
}
|
|
|
|
// nBWidth, nBHeight is the pixel size of the neede bitmap. To not need to scale it
|
|
// in vcl many times, create a size-optimized version
|
|
const Size aNeededBitmapSizePixel(nBWidth, nBHeight);
|
|
|
|
if(aNeededBitmapSizePixel != aBitmapEx.GetSizePixel())
|
|
{
|
|
aBitmapEx.Scale(aNeededBitmapSizePixel);
|
|
}
|
|
|
|
// prepare OutDev
|
|
const Point aEmptyPoint(0, 0);
|
|
const Rectangle aVisiblePixel(aEmptyPoint, mpOutputDevice->GetOutputSizePixel());
|
|
const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
|
|
mpOutputDevice->EnableMapMode(false);
|
|
|
|
for(sal_Int32 nXPos(nBLeft); nXPos < aObjTL.X() + nOWidth; nXPos += nBWidth)
|
|
{
|
|
for(sal_Int32 nYPos(nBTop); nYPos < aObjTL.Y() + nOHeight; nYPos += nBHeight)
|
|
{
|
|
const Rectangle aOutRectPixel(Point(nXPos, nYPos), aNeededBitmapSizePixel);
|
|
|
|
if(aOutRectPixel.IsOver(aVisiblePixel))
|
|
{
|
|
mpOutputDevice->DrawBitmapEx(aOutRectPixel.TopLeft(), aBitmapEx);
|
|
}
|
|
}
|
|
}
|
|
|
|
// restore OutDev
|
|
mpOutputDevice->EnableMapMode(bWasEnabled);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!bPrimitiveAccepted)
|
|
{
|
|
// do not accept, use decomposition
|
|
process(rFillBitmapCandidate.get2DDecomposition(getViewInformation2D()));
|
|
}
|
|
}
|
|
|
|
// direct draw of gradient
|
|
void VclProcessor2D::RenderPolyPolygonGradientPrimitive2D(const primitive2d::PolyPolygonGradientPrimitive2D& rPolygonCandidate)
|
|
{
|
|
const attribute::FillGradientAttribute& rGradient(rPolygonCandidate.getFillGradient());
|
|
basegfx::BColor aStartColor(maBColorModifierStack.getModifiedColor(rGradient.getStartColor()));
|
|
basegfx::BColor aEndColor(maBColorModifierStack.getModifiedColor(rGradient.getEndColor()));
|
|
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
|
|
aLocalPolyPolygon.transform(maCurrentTransformation);
|
|
|
|
if(aStartColor == aEndColor)
|
|
{
|
|
// no gradient at all, draw as polygon
|
|
mpOutputDevice->SetLineColor();
|
|
mpOutputDevice->SetFillColor(Color(aStartColor));
|
|
mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
|
|
}
|
|
else
|
|
{
|
|
impDrawGradientToOutDev(
|
|
*mpOutputDevice, aLocalPolyPolygon, rGradient.getStyle(), rGradient.getSteps(),
|
|
aStartColor, aEndColor, rGradient.getBorder(),
|
|
-rGradient.getAngle(), rGradient.getOffsetX(), rGradient.getOffsetY(), false);
|
|
}
|
|
}
|
|
|
|
// direct draw of PolyPolygon with color
|
|
void VclProcessor2D::RenderPolyPolygonColorPrimitive2D(const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate)
|
|
{
|
|
const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor()));
|
|
mpOutputDevice->SetFillColor(Color(aPolygonColor));
|
|
mpOutputDevice->SetLineColor();
|
|
|
|
basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon());
|
|
aLocalPolyPolygon.transform(maCurrentTransformation);
|
|
|
|
mpOutputDevice->DrawPolyPolygon(PolyPolygon(aLocalPolyPolygon));
|
|
}
|
|
|
|
// direct draw of MetaFile
|
|
void VclProcessor2D::RenderMetafilePrimitive2D(const primitive2d::MetafilePrimitive2D& rMetaCandidate)
|
|
{
|
|
// decompose matrix to check for shear, rotate and mirroring
|
|
basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rMetaCandidate.getTransform());
|
|
basegfx::B2DVector aScale, aTranslate;
|
|
double fRotate, fShearX;
|
|
aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX);
|
|
|
|
// get BoundRect
|
|
basegfx::B2DRange aOutlineRange(rMetaCandidate.getB2DRange(getViewInformation2D()));
|
|
aOutlineRange.transform(maCurrentTransformation);
|
|
const Rectangle aDestRectView(
|
|
basegfx::fround(aOutlineRange.getMinX()), basegfx::fround(aOutlineRange.getMinY()),
|
|
basegfx::fround(aOutlineRange.getMaxX()), basegfx::fround(aOutlineRange.getMaxY()));
|
|
|
|
// get metafile (copy it)
|
|
GDIMetaFile aMetaFile;
|
|
|
|
if(maBColorModifierStack.count())
|
|
{
|
|
const basegfx::BColor aRGBBaseColor(0, 0, 0);
|
|
const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(aRGBBaseColor));
|
|
aMetaFile = rMetaCandidate.getMetaFile().GetMonochromeMtf(Color(aRGBColor));
|
|
}
|
|
else
|
|
{
|
|
aMetaFile = rMetaCandidate.getMetaFile();
|
|
}
|
|
|
|
// rotation
|
|
if(!basegfx::fTools::equalZero(fRotate))
|
|
{
|
|
double fRotation((fRotate / F_PI180) * -10.0);
|
|
aMetaFile.Rotate((sal_uInt16)(fRotation));
|
|
}
|
|
|
|
// paint it
|
|
aMetaFile.WindStart();
|
|
aMetaFile.Play(mpOutputDevice, aDestRectView.TopLeft(), aDestRectView.GetSize());
|
|
}
|
|
|
|
// mask group. Force output to VDev and create mask from given mask
|
|
void VclProcessor2D::RenderMaskPrimitive2D(const primitive2d::MaskPrimitive2D& rMaskCandidate)
|
|
{
|
|
if(rMaskCandidate.getChildren().hasElements())
|
|
{
|
|
basegfx::B2DPolyPolygon aMask(rMaskCandidate.getMask());
|
|
aMask.transform(maCurrentTransformation);
|
|
const basegfx::B2DRange aRange(basegfx::tools::getRange(aMask));
|
|
impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
|
|
|
|
if(aBufferDevice.isVisible())
|
|
{
|
|
// remember last OutDev and set to content
|
|
OutputDevice* pLastOutputDevice = mpOutputDevice;
|
|
mpOutputDevice = &aBufferDevice.getContent();
|
|
|
|
// paint to it
|
|
process(rMaskCandidate.getChildren());
|
|
|
|
// back to old OutDev
|
|
mpOutputDevice = pLastOutputDevice;
|
|
|
|
// draw mask
|
|
VirtualDevice& rMask = aBufferDevice.getMask();
|
|
rMask.SetLineColor();
|
|
rMask.SetFillColor(COL_BLACK);
|
|
rMask.DrawPolyPolygon(PolyPolygon(aMask));
|
|
|
|
// dump buffer to outdev
|
|
aBufferDevice.paint();
|
|
}
|
|
}
|
|
}
|
|
|
|
// modified color group. Force output to unified color.
|
|
void VclProcessor2D::RenderModifiedColorPrimitive2D(const primitive2d::ModifiedColorPrimitive2D& rModifiedCandidate)
|
|
{
|
|
if(rModifiedCandidate.getChildren().hasElements())
|
|
{
|
|
maBColorModifierStack.push(rModifiedCandidate.getColorModifier());
|
|
process(rModifiedCandidate.getChildren());
|
|
maBColorModifierStack.pop();
|
|
}
|
|
}
|
|
|
|
// sub-transparence group. Draw to VDev first.
|
|
void VclProcessor2D::RenderAlphaPrimitive2D(const primitive2d::AlphaPrimitive2D& rTransCandidate)
|
|
{
|
|
if(rTransCandidate.getChildren().hasElements())
|
|
{
|
|
basegfx::B2DRange aRange(primitive2d::getB2DRangeFromPrimitive2DSequence(rTransCandidate.getChildren(), getViewInformation2D()));
|
|
aRange.transform(maCurrentTransformation);
|
|
impBufferDevice aBufferDevice(*mpOutputDevice, aRange);
|
|
|
|
if(aBufferDevice.isVisible())
|
|
{
|
|
// remember last OutDev and set to content
|
|
OutputDevice* pLastOutputDevice = mpOutputDevice;
|
|
mpOutputDevice = &aBufferDevice.getContent();
|
|
|
|
// paint content to it
|
|
process(rTransCandidate.getChildren());
|
|
|
|
// set to mask
|
|
mpOutputDevice = &aBufferDevice.getAlpha();
|
|
|
|
// when painting alpha masks, reset the color stack
|
|
basegfx::BColorModifierStack aLastBColorModifierStack(maBColorModifierStack);
|
|
maBColorModifierStack = basegfx::BColorModifierStack();
|
|
|
|
// paint mask to it
|
|
process(rTransCandidate.getAlpha());
|
|
|
|
// back to old color stack
|
|
maBColorModifierStack = aLastBColorModifierStack;
|
|
|
|
// back to old OutDev
|
|
mpOutputDevice = pLastOutputDevice;
|
|
|
|
// dump buffer to outdev
|
|
aBufferDevice.paint();
|
|
}
|
|
}
|
|
}
|
|
|
|
// transform group.
|
|
void VclProcessor2D::RenderTransformPrimitive2D(const primitive2d::TransformPrimitive2D& rTransformCandidate)
|
|
{
|
|
// remember current transformation
|
|
basegfx::B2DHomMatrix aLastCurrentTransformation(maCurrentTransformation);
|
|
|
|
// create new transformations
|
|
maCurrentTransformation = maCurrentTransformation * rTransformCandidate.getTransformation();
|
|
|
|
// let break down
|
|
process(rTransformCandidate.getChildren());
|
|
|
|
// restore transformations
|
|
maCurrentTransformation = aLastCurrentTransformation;
|
|
}
|
|
|
|
// marker
|
|
void VclProcessor2D::RenderMarkerArrayPrimitive2D(const primitive2d::MarkerArrayPrimitive2D& rMarkArrayCandidate)
|
|
{
|
|
const std::vector< basegfx::B2DPoint >& rPositions = rMarkArrayCandidate.getPositions();
|
|
const basegfx::BColor aRGBColor(maBColorModifierStack.getModifiedColor(rMarkArrayCandidate.getRGBColor()));
|
|
const Color aColor(aRGBColor);
|
|
|
|
if(primitive2d::MARKERSTYLE2D_POINT == rMarkArrayCandidate.getStyle())
|
|
{
|
|
for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++)
|
|
{
|
|
const basegfx::B2DPoint aViewPosition(maCurrentTransformation * (*aIter));
|
|
const Point aPos(basegfx::fround(aViewPosition.getX()), basegfx::fround(aViewPosition.getY()));
|
|
|
|
mpOutputDevice->DrawPixel(aPos, aColor);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const bool bWasEnabled(mpOutputDevice->IsMapModeEnabled());
|
|
|
|
for(std::vector< basegfx::B2DPoint >::const_iterator aIter(rPositions.begin()); aIter != rPositions.end(); aIter++)
|
|
{
|
|
const basegfx::B2DPoint aViewPosition(maCurrentTransformation * (*aIter));
|
|
Point aPos(basegfx::fround(aViewPosition.getX()), basegfx::fround(aViewPosition.getY()));
|
|
aPos = mpOutputDevice->LogicToPixel(aPos);
|
|
|
|
mpOutputDevice->EnableMapMode(false);
|
|
|
|
switch(rMarkArrayCandidate.getStyle())
|
|
{
|
|
case primitive2d::MARKERSTYLE2D_CROSS :
|
|
{
|
|
mpOutputDevice->DrawPixel(aPos, aColor);
|
|
mpOutputDevice->DrawPixel(Point(aPos.X() - 1L, aPos.Y()), aColor);
|
|
mpOutputDevice->DrawPixel(Point(aPos.X() + 1L, aPos.Y()), aColor);
|
|
mpOutputDevice->DrawPixel(Point(aPos.X(), aPos.Y() - 1L), aColor);
|
|
mpOutputDevice->DrawPixel(Point(aPos.X(), aPos.Y() + 1L), aColor);
|
|
|
|
break;
|
|
}
|
|
case primitive2d::MARKERSTYLE2D_GLUEPOINT :
|
|
{
|
|
// backpen
|
|
mpOutputDevice->SetLineColor(aColor);
|
|
mpOutputDevice->DrawLine(aPos + Point(-2, -3), aPos + Point(+3, +2));
|
|
mpOutputDevice->DrawLine(aPos + Point(-3, -2), aPos + Point(+2, +3));
|
|
mpOutputDevice->DrawLine(aPos + Point(-3, +2), aPos + Point(+2, -3));
|
|
mpOutputDevice->DrawLine(aPos + Point(-2, +3), aPos + Point(+3, -2));
|
|
|
|
// frontpen (hard coded)
|
|
Color aFrontColor(COL_LIGHTBLUE);
|
|
const basegfx::BColor aRGBFrontColor(maBColorModifierStack.getModifiedColor(aFrontColor.getBColor()));
|
|
aFrontColor = Color(aRGBFrontColor);
|
|
|
|
mpOutputDevice->SetLineColor(aFrontColor);
|
|
mpOutputDevice->DrawLine(aPos + Point(-2, -2), aPos + Point(+2, +2));
|
|
mpOutputDevice->DrawLine(aPos + Point(-2, +2), aPos + Point(+2, -2));
|
|
|
|
break;
|
|
}
|
|
default : // primitive2d::MARKERSTYLE2D_POINT
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
mpOutputDevice->EnableMapMode(bWasEnabled);
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// internal processing support
|
|
|
|
void VclProcessor2D::process(const primitive2d::Primitive2DSequence& rSource)
|
|
{
|
|
if(rSource.hasElements())
|
|
{
|
|
const sal_Int32 nCount(rSource.getLength());
|
|
|
|
for(sal_Int32 a(0L); a < nCount; a++)
|
|
{
|
|
// get reference
|
|
const primitive2d::Primitive2DReference xReference(rSource[a]);
|
|
|
|
if(xReference.is())
|
|
{
|
|
// try to cast to BasePrimitive2D implementation
|
|
const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get());
|
|
|
|
if(pBasePrimitive)
|
|
{
|
|
// it is a BasePrimitive2D implementation, use getPrimitiveID() call for switch
|
|
switch(pBasePrimitive->getPrimitiveID())
|
|
{
|
|
case Create2DPrimitiveID('2','T','S','i') :
|
|
{
|
|
// directdraw of text simple portion
|
|
RenderTextSimplePortionPrimitive2D(static_cast< const primitive2d::TextSimplePortionPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','P','H','a') :
|
|
{
|
|
// direct draw of hairline
|
|
RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','B','i','t') :
|
|
{
|
|
// direct draw of transformed BitmapEx primitive
|
|
RenderBitmapPrimitive2D(static_cast< const primitive2d::BitmapPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','F','B','i') :
|
|
{
|
|
// direct draw of fillBitmapPrimitive
|
|
RenderFillBitmapPrimitive2D(static_cast< const primitive2d::FillBitmapPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','P','P','G') :
|
|
{
|
|
// direct draw of gradient
|
|
RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','P','P','C') :
|
|
{
|
|
// direct draw of PolyPolygon with color
|
|
RenderPolyPolygonColorPrimitive2D(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','M','e','t') :
|
|
{
|
|
// direct draw of MetaFile
|
|
RenderMetafilePrimitive2D(static_cast< const primitive2d::MetafilePrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','M','a','s') :
|
|
{
|
|
// mask group. Force output to VDev and create mask from given mask
|
|
RenderMaskPrimitive2D(static_cast< const primitive2d::MaskPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','M','C','o') :
|
|
{
|
|
// modified color group. Force output to unified color.
|
|
RenderModifiedColorPrimitive2D(static_cast< const primitive2d::ModifiedColorPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','A','l','p') :
|
|
{
|
|
// sub-transparence group. Draw to VDev first.
|
|
RenderAlphaPrimitive2D(static_cast< const primitive2d::AlphaPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','T','r','a') :
|
|
{
|
|
// transform group.
|
|
RenderTransformPrimitive2D(static_cast< const primitive2d::TransformPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
case Create2DPrimitiveID('2','M','a','r') :
|
|
{
|
|
// marker array
|
|
RenderMarkerArrayPrimitive2D(static_cast< const primitive2d::MarkerArrayPrimitive2D& >(*pBasePrimitive));
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
// process recursively
|
|
process(pBasePrimitive->get2DDecomposition(getViewInformation2D()));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// unknown implementation, use UNO API call instead and process recursively
|
|
com::sun::star::graphic::Primitive2DParameters aPrimitive2DParameters;
|
|
|
|
basegfx::unotools::affineMatrixFromHomMatrix(aPrimitive2DParameters.ViewTransformation, getViewInformation2D().getViewTransformation());
|
|
aPrimitive2DParameters.Viewport = basegfx::unotools::rectangle2DFromB2DRectangle(getViewInformation2D().getViewport());
|
|
aPrimitive2DParameters.Time = getViewInformation2D().getViewTime();
|
|
|
|
process(xReference->getDecomposition(aPrimitive2DParameters));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VclProcessor2D::VclProcessor2D(
|
|
const geometry::ViewInformation2D& rViewInformation,
|
|
OutputDevice& rOutDev)
|
|
: BaseProcessor2D(rViewInformation),
|
|
mbOutputToRecordingMetaFile(false)
|
|
{
|
|
// initialize destination OutDev
|
|
mpOutputDevice = &rOutDev;
|
|
|
|
// check if output is recorded to metafile
|
|
const GDIMetaFile* pMetaFile = mpOutputDevice->GetConnectMetaFile();
|
|
mbOutputToRecordingMetaFile = (pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
|
|
|
|
if(mbOutputToRecordingMetaFile)
|
|
{
|
|
// draw to logic coordinates, do not initialize maCurrentTransformation to viewTransformation,
|
|
// do not change MapMode of destination
|
|
}
|
|
else
|
|
{
|
|
// prepare maCurrentTransformation matrix with viewTransformation to go directly to pixels
|
|
maCurrentTransformation = rViewInformation.getViewTransformation();
|
|
|
|
// prepare output to pixels
|
|
mpOutputDevice->Push(PUSH_MAPMODE);
|
|
mpOutputDevice->SetMapMode();
|
|
}
|
|
}
|
|
|
|
VclProcessor2D::~VclProcessor2D()
|
|
{
|
|
if(mbOutputToRecordingMetaFile)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
// restore MapMode
|
|
mpOutputDevice->Pop();
|
|
}
|
|
}
|
|
} // end of namespace processor2d
|
|
} // end of namespace drawinglayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// eof
|