forked from amazingfate/loongoffice
2009-01-27 15:15:53 +0100 aw r266999 : #i97982# corrected small error in ObjectContactOfPageView::isOutputToPDFFile() 2009-01-15 16:02:22 +0100 aw r266378 : #i89872# corrected SdrModel::ImpSetUIUnit to not lose numeric information 2009-01-14 15:16:43 +0100 aw r266309 : #i98072# adde d text suppression for FontworkGallery AutoShapes in ViewContactOfSdrObjCustomShape::createViewIndependentPrimitive2DSequence 2009-01-14 12:35:32 +0100 aw r266283 : #i97878# added TRGetBaseGeometry/TRSetBaseGeometry implementations to SdrMeasureObj 2009-01-14 12:06:47 +0100 aw r266274 : #i97981# corrected the interpretation of bBehaveCompatibleToPaintVersion for line attribute in SdrOle2Primitive2D::createLocalDecomposition 2009-01-14 11:54:07 +0100 aw r266272 : #i97982# added #i97772# to have a correct ChartPrettyPainter output for ChartPrettyPainter 2009-01-14 11:53:13 +0100 aw r266271 : #i97982# added support for ChartPrettyPainter for PDF export 2009-01-13 16:19:19 +0100 aw r266234 : #i96708# adapted RenderBitmapPrimitive2D_self to work with metafile recording and PDF exporting
279 lines
11 KiB
C++
279 lines
11 KiB
C++
/*************************************************************************
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* $RCSfile: vclhelperbitmaprender.cxx,v $
|
|
*
|
|
* $Revision: 1.3 $
|
|
*
|
|
* last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
|
|
*
|
|
* 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
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_drawinglayer.hxx"
|
|
|
|
#include <vclhelperbitmaprender.hxx>
|
|
#include <goodies/grfmgr.hxx>
|
|
#include <basegfx/vector/b2dvector.hxx>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <basegfx/range/b2drange.hxx>
|
|
#include <vcl/outdev.hxx>
|
|
#include <vclhelperbitmaptransform.hxx>
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// support for different kinds of bitmap rendering using vcl
|
|
|
|
namespace drawinglayer
|
|
{
|
|
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));
|
|
|
|
// #i96708# check if Metafile is recorded
|
|
const GDIMetaFile* pMetaFile = rOutDev.GetConnectMetaFile();
|
|
const bool bRecordToMetaFile(pMetaFile && pMetaFile->IsRecord() && !pMetaFile->IsPause());
|
|
|
|
// intersect with output pixel size, but only
|
|
// when not recording to metafile
|
|
const Rectangle aOutputRectPixel(Point(), rOutDev.GetOutputSizePixel());
|
|
Rectangle aCroppedRectPixel(bRecordToMetaFile ? aDestRectPixel : aDestRectPixel.GetIntersection(aOutputRectPixel));
|
|
|
|
if(!aCroppedRectPixel.IsEmpty())
|
|
{
|
|
// as maximum for destination, orientate at SourceSizePixel, but
|
|
// take a rotation of 45 degrees (sqrt(2)) as maximum expansion into account
|
|
const Size aSourceSizePixel(rBitmapEx.GetSizePixel());
|
|
const double fMaximumArea(
|
|
(double)aSourceSizePixel.getWidth() *
|
|
(double)aSourceSizePixel.getHeight() *
|
|
1.4142136); // 1.4142136 taken as sqrt(2.0)
|
|
|
|
// test if discrete view size (pixel) maybe too big and limit it
|
|
const double fArea(aCroppedRectPixel.getWidth() * aCroppedRectPixel.getHeight());
|
|
const bool bNeedToReduce(fArea > fMaximumArea);
|
|
double fReduceFactor(1.0);
|
|
|
|
if(bNeedToReduce)
|
|
{
|
|
fReduceFactor = sqrt(fMaximumArea / fArea);
|
|
aCroppedRectPixel.setWidth(basegfx::fround(aCroppedRectPixel.getWidth() * fReduceFactor));
|
|
aCroppedRectPixel.setHeight(basegfx::fround(aCroppedRectPixel.getHeight() * fReduceFactor));
|
|
}
|
|
|
|
// build transform from pixel in aDestination to pixel in rBitmapEx
|
|
basegfx::B2DHomMatrix aTransform;
|
|
|
|
// from relative in aCroppedRectPixel to relative in aDestRectPixel
|
|
// No need to take bNeedToReduce into account, TopLeft is unchanged
|
|
aTransform.translate(aCroppedRectPixel.Left() - aDestRectPixel.Left(), aCroppedRectPixel.Top() - aDestRectPixel.Top());
|
|
|
|
// from relative in aDestRectPixel to absolute Logic. Here it
|
|
// is essential to adapt to reduce factor (if used)
|
|
double fAdaptedDRPWidth((double)aDestRectPixel.getWidth());
|
|
double fAdaptedDRPHeight((double)aDestRectPixel.getHeight());
|
|
|
|
if(bNeedToReduce)
|
|
{
|
|
fAdaptedDRPWidth *= fReduceFactor;
|
|
fAdaptedDRPHeight *= fReduceFactor;
|
|
}
|
|
|
|
aTransform.scale(aDestRectLogic.getWidth() / fAdaptedDRPWidth, aDestRectLogic.getHeight() / fAdaptedDRPHeight);
|
|
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
|
|
aTransform.scale(aSourceSizePixel.getWidth() - 1L, aSourceSizePixel.getHeight() - 1L);
|
|
|
|
// create bitmap using source, destination and linear back-transformation
|
|
BitmapEx aDestination = impTransformBitmapEx(rBitmapEx, aCroppedRectPixel, aTransform);
|
|
|
|
// paint
|
|
if(bNeedToReduce)
|
|
{
|
|
// paint in target size
|
|
const double fFactor(1.0 / fReduceFactor);
|
|
const Size aDestSizePixel(
|
|
basegfx::fround(aCroppedRectPixel.getWidth() * fFactor),
|
|
basegfx::fround(aCroppedRectPixel.getHeight() * fFactor));
|
|
|
|
if(bRecordToMetaFile)
|
|
{
|
|
rOutDev.DrawBitmapEx(
|
|
rOutDev.PixelToLogic(aCroppedRectPixel.TopLeft()),
|
|
rOutDev.PixelToLogic(aDestSizePixel),
|
|
aDestination);
|
|
}
|
|
else
|
|
{
|
|
const bool bWasEnabled(rOutDev.IsMapModeEnabled());
|
|
rOutDev.EnableMapMode(false);
|
|
|
|
rOutDev.DrawBitmapEx(
|
|
aCroppedRectPixel.TopLeft(),
|
|
aDestSizePixel,
|
|
aDestination);
|
|
|
|
rOutDev.EnableMapMode(bWasEnabled);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(bRecordToMetaFile)
|
|
{
|
|
rOutDev.DrawBitmapEx(
|
|
rOutDev.PixelToLogic(aCroppedRectPixel.TopLeft()),
|
|
aDestination);
|
|
}
|
|
else
|
|
{
|
|
const bool bWasEnabled(rOutDev.IsMapModeEnabled());
|
|
rOutDev.EnableMapMode(false);
|
|
|
|
rOutDev.DrawBitmapEx(
|
|
aCroppedRectPixel.TopLeft(),
|
|
aDestination);
|
|
|
|
rOutDev.EnableMapMode(bWasEnabled);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // end of namespace drawinglayer
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// eof
|