1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: vclhelperbitmaprender.cxx,v $
9 * last change: $Author: aw $ $Date: 2008-05-27 14:11:21 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <vclhelperbitmaprender.hxx>
40 #include <goodies/grfmgr.hxx>
41 #include <basegfx/vector/b2dvector.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <basegfx/range/b2drange.hxx>
44 #include <vcl/outdev.hxx>
45 #include <vclhelperbitmaptransform.hxx>
47 //////////////////////////////////////////////////////////////////////////////
48 // support for different kinds of bitmap rendering using vcl
50 namespace drawinglayer
52 void RenderBitmapPrimitive2D_GraphicManager(
53 OutputDevice
& rOutDev
,
54 const BitmapEx
& rBitmapEx
,
55 const basegfx::B2DHomMatrix
& rTransform
)
58 GraphicAttr aAttributes
;
60 // decompose matrix to check for shear, rotate and mirroring
61 basegfx::B2DVector aScale
, aTranslate
;
62 double fRotate
, fShearX
;
63 rTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
66 aAttributes
.SetMirrorFlags(
67 (basegfx::fTools::less(aScale
.getX(), 0.0) ? BMP_MIRROR_HORZ
: 0)|
68 (basegfx::fTools::less(aScale
.getY(), 0.0) ? BMP_MIRROR_VERT
: 0));
71 if(!basegfx::fTools::equalZero(fRotate
))
73 double fRotation(fmod(3600.0 - (fRotate
* (10.0 / F_PI180
)), 3600.0));
74 aAttributes
.SetRotation((sal_uInt16
)(fRotation
));
78 basegfx::B2DRange
aOutlineRange(0.0, 0.0, 1.0, 1.0);
80 if(basegfx::fTools::equalZero(fRotate
))
82 aOutlineRange
.transform(rTransform
);
86 // if rotated, create the unrotated output rectangle for the GraphicManager paint
87 basegfx::B2DHomMatrix aSimpleObjectMatrix
;
89 aSimpleObjectMatrix
.scale(fabs(aScale
.getX()), fabs(aScale
.getY()));
90 aSimpleObjectMatrix
.translate(aTranslate
.getX(), aTranslate
.getY());
92 aOutlineRange
.transform(aSimpleObjectMatrix
);
96 const Rectangle
aDestRectPixel(
97 basegfx::fround(aOutlineRange
.getMinX()), basegfx::fround(aOutlineRange
.getMinY()),
98 basegfx::fround(aOutlineRange
.getMaxX()), basegfx::fround(aOutlineRange
.getMaxY()));
100 // paint it using GraphicManager
101 Graphic
aGraphic(rBitmapEx
);
102 GraphicObject
aGraphicObject(aGraphic
);
103 aGraphicObject
.Draw(&rOutDev
, aDestRectPixel
.TopLeft(), aDestRectPixel
.GetSize(), &aAttributes
);
106 void RenderBitmapPrimitive2D_BitmapEx(
107 OutputDevice
& rOutDev
,
108 const BitmapEx
& rBitmapEx
,
109 const basegfx::B2DHomMatrix
& rTransform
)
111 // only translate and scale, use vcl's DrawBitmapEx().
112 BitmapEx
aContent(rBitmapEx
);
114 // prepare dest coor. Necessary to expand since vcl's DrawBitmapEx draws one pix less
115 basegfx::B2DRange
aOutlineRange(0.0, 0.0, 1.0, 1.0);
116 aOutlineRange
.transform(rTransform
);
117 const Rectangle
aDestRectPixel(
118 basegfx::fround(aOutlineRange
.getMinX()), basegfx::fround(aOutlineRange
.getMinY()),
119 basegfx::fround(aOutlineRange
.getMaxX()), basegfx::fround(aOutlineRange
.getMaxY()));
121 // decompose matrix to check for shear, rotate and mirroring
122 basegfx::B2DVector aScale
, aTranslate
;
123 double fRotate
, fShearX
;
124 rTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
127 sal_uInt32
nMirrorFlags(BMP_MIRROR_NONE
);
129 if(basegfx::fTools::less(aScale
.getX(), 0.0))
131 nMirrorFlags
|= BMP_MIRROR_HORZ
;
134 if(basegfx::fTools::less(aScale
.getY(), 0.0))
136 nMirrorFlags
|= BMP_MIRROR_VERT
;
139 if(BMP_MIRROR_NONE
!= nMirrorFlags
)
141 aContent
.Mirror(nMirrorFlags
);
145 rOutDev
.DrawBitmapEx(aDestRectPixel
.TopLeft(), aDestRectPixel
.GetSize(), aContent
);
148 void RenderBitmapPrimitive2D_self(
149 OutputDevice
& rOutDev
,
150 const BitmapEx
& rBitmapEx
,
151 const basegfx::B2DHomMatrix
& rTransform
)
153 // process self with free transformation (containing shear and rotate). Get dest rect in pixels.
154 basegfx::B2DRange
aOutlineRange(0.0, 0.0, 1.0, 1.0);
155 aOutlineRange
.transform(rTransform
);
156 const Rectangle
aDestRectLogic(
157 basegfx::fround(aOutlineRange
.getMinX()), basegfx::fround(aOutlineRange
.getMinY()),
158 basegfx::fround(aOutlineRange
.getMaxX()), basegfx::fround(aOutlineRange
.getMaxY()));
159 const Rectangle
aDestRectPixel(rOutDev
.LogicToPixel(aDestRectLogic
));
161 // #i96708# check if Metafile is recorded
162 const GDIMetaFile
* pMetaFile
= rOutDev
.GetConnectMetaFile();
163 const bool bRecordToMetaFile(pMetaFile
&& pMetaFile
->IsRecord() && !pMetaFile
->IsPause());
165 // intersect with output pixel size, but only
166 // when not recording to metafile
167 const Rectangle
aOutputRectPixel(Point(), rOutDev
.GetOutputSizePixel());
168 Rectangle
aCroppedRectPixel(bRecordToMetaFile
? aDestRectPixel
: aDestRectPixel
.GetIntersection(aOutputRectPixel
));
170 if(!aCroppedRectPixel
.IsEmpty())
172 // as maximum for destination, orientate at SourceSizePixel, but
173 // take a rotation of 45 degrees (sqrt(2)) as maximum expansion into account
174 const Size
aSourceSizePixel(rBitmapEx
.GetSizePixel());
175 const double fMaximumArea(
176 (double)aSourceSizePixel
.getWidth() *
177 (double)aSourceSizePixel
.getHeight() *
178 1.4142136); // 1.4142136 taken as sqrt(2.0)
180 // test if discrete view size (pixel) maybe too big and limit it
181 const double fArea(aCroppedRectPixel
.getWidth() * aCroppedRectPixel
.getHeight());
182 const bool bNeedToReduce(fArea
> fMaximumArea
);
183 double fReduceFactor(1.0);
187 fReduceFactor
= sqrt(fMaximumArea
/ fArea
);
188 aCroppedRectPixel
.setWidth(basegfx::fround(aCroppedRectPixel
.getWidth() * fReduceFactor
));
189 aCroppedRectPixel
.setHeight(basegfx::fround(aCroppedRectPixel
.getHeight() * fReduceFactor
));
192 // build transform from pixel in aDestination to pixel in rBitmapEx
193 basegfx::B2DHomMatrix aTransform
;
195 // from relative in aCroppedRectPixel to relative in aDestRectPixel
196 // No need to take bNeedToReduce into account, TopLeft is unchanged
197 aTransform
.translate(aCroppedRectPixel
.Left() - aDestRectPixel
.Left(), aCroppedRectPixel
.Top() - aDestRectPixel
.Top());
199 // from relative in aDestRectPixel to absolute Logic. Here it
200 // is essential to adapt to reduce factor (if used)
201 double fAdaptedDRPWidth((double)aDestRectPixel
.getWidth());
202 double fAdaptedDRPHeight((double)aDestRectPixel
.getHeight());
206 fAdaptedDRPWidth
*= fReduceFactor
;
207 fAdaptedDRPHeight
*= fReduceFactor
;
210 aTransform
.scale(aDestRectLogic
.getWidth() / fAdaptedDRPWidth
, aDestRectLogic
.getHeight() / fAdaptedDRPHeight
);
211 aTransform
.translate(aDestRectLogic
.Left(), aDestRectLogic
.Top());
213 // from absolute in Logic to unified object coordinates (0.0 .. 1.0 in x and y)
214 basegfx::B2DHomMatrix
aInvBitmapTransform(rTransform
);
215 aInvBitmapTransform
.invert();
216 aTransform
= aInvBitmapTransform
* aTransform
;
218 // from unit object coordinates to rBitmapEx pixel coordintes
219 aTransform
.scale(aSourceSizePixel
.getWidth() - 1L, aSourceSizePixel
.getHeight() - 1L);
221 // create bitmap using source, destination and linear back-transformation
222 BitmapEx aDestination
= impTransformBitmapEx(rBitmapEx
, aCroppedRectPixel
, aTransform
);
227 // paint in target size
228 const double fFactor(1.0 / fReduceFactor
);
229 const Size
aDestSizePixel(
230 basegfx::fround(aCroppedRectPixel
.getWidth() * fFactor
),
231 basegfx::fround(aCroppedRectPixel
.getHeight() * fFactor
));
233 if(bRecordToMetaFile
)
235 rOutDev
.DrawBitmapEx(
236 rOutDev
.PixelToLogic(aCroppedRectPixel
.TopLeft()),
237 rOutDev
.PixelToLogic(aDestSizePixel
),
242 const bool bWasEnabled(rOutDev
.IsMapModeEnabled());
243 rOutDev
.EnableMapMode(false);
245 rOutDev
.DrawBitmapEx(
246 aCroppedRectPixel
.TopLeft(),
250 rOutDev
.EnableMapMode(bWasEnabled
);
255 if(bRecordToMetaFile
)
257 rOutDev
.DrawBitmapEx(
258 rOutDev
.PixelToLogic(aCroppedRectPixel
.TopLeft()),
263 const bool bWasEnabled(rOutDev
.IsMapModeEnabled());
264 rOutDev
.EnableMapMode(false);
266 rOutDev
.DrawBitmapEx(
267 aCroppedRectPixel
.TopLeft(),
270 rOutDev
.EnableMapMode(bWasEnabled
);
275 } // end of namespace drawinglayer
277 //////////////////////////////////////////////////////////////////////////////