fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / drawinglayer / source / processor2d / vclhelperbitmaptransform.cxx
blob6033eb47a9c0042660d4f1c5c6b337efdfb41d13
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <vclhelperbitmaptransform.hxx>
21 #include <vcl/bmpacc.hxx>
22 #include <basegfx/point/b2dpoint.hxx>
23 #include <basegfx/color/bcolormodifier.hxx>
25 //////////////////////////////////////////////////////////////////////////////
26 // support for rendering Bitmap and BitmapEx contents
28 namespace drawinglayer
30 namespace
32 void impSmoothPoint(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
34 double fDeltaX(rSource.getX() - nIntX);
35 double fDeltaY(rSource.getY() - nIntY);
36 sal_Int32 nIndX(0L);
37 sal_Int32 nIndY(0L);
39 if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
41 nIndX++;
43 else if(fDeltaX < 0.0 && nIntX >= 1L)
45 fDeltaX = -fDeltaX;
46 nIndX--;
49 if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
51 nIndY++;
53 else if(fDeltaY < 0.0 && nIntY >= 1L)
55 fDeltaY = -fDeltaY;
56 nIndY--;
59 if(nIndX || nIndY)
61 const double fColorToReal(1.0 / 255.0);
62 double fR(rValue.GetRed() * fColorToReal);
63 double fG(rValue.GetGreen() * fColorToReal);
64 double fB(rValue.GetBlue() * fColorToReal);
65 double fRBottom(0.0), fGBottom(0.0), fBBottom(0.0);
67 if(nIndX)
69 const double fMulA(fDeltaX * fColorToReal);
70 double fMulB(1.0 - fDeltaX);
71 const BitmapColor aTopPartner(rRead.GetColor(nIntY, nIntX + nIndX));
73 fR = (fR * fMulB) + (aTopPartner.GetRed() * fMulA);
74 fG = (fG * fMulB) + (aTopPartner.GetGreen() * fMulA);
75 fB = (fB * fMulB) + (aTopPartner.GetBlue() * fMulA);
77 if(nIndY)
79 fMulB *= fColorToReal;
80 const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
81 const BitmapColor aBottomPartner(rRead.GetColor(nIntY + nIndY, nIntX + nIndX));
83 fRBottom = (aBottom.GetRed() * fMulB) + (aBottomPartner.GetRed() * fMulA);
84 fGBottom = (aBottom.GetGreen() * fMulB) + (aBottomPartner.GetGreen() * fMulA);
85 fBBottom = (aBottom.GetBlue() * fMulB) + (aBottomPartner.GetBlue() * fMulA);
89 if(nIndY)
91 if(!nIndX)
93 const BitmapColor aBottom(rRead.GetColor(nIntY + nIndY, nIntX));
95 fRBottom = aBottom.GetRed() * fColorToReal;
96 fGBottom = aBottom.GetGreen() * fColorToReal;
97 fBBottom = aBottom.GetBlue() * fColorToReal;
100 const double fMulB(1.0 - fDeltaY);
102 fR = (fR * fMulB) + (fRBottom * fDeltaY);
103 fG = (fG * fMulB) + (fGBottom * fDeltaY);
104 fB = (fB * fMulB) + (fBBottom * fDeltaY);
107 rValue.SetRed((sal_uInt8)(fR * 255.0));
108 rValue.SetGreen((sal_uInt8)(fG * 255.0));
109 rValue.SetBlue((sal_uInt8)(fB * 255.0));
113 void impSmoothIndex(BitmapColor& rValue, const basegfx::B2DPoint& rSource, sal_Int32 nIntX, sal_Int32 nIntY, BitmapReadAccess& rRead)
115 double fDeltaX(rSource.getX() - nIntX);
116 double fDeltaY(rSource.getY() - nIntY);
117 sal_Int32 nIndX(0L);
118 sal_Int32 nIndY(0L);
120 if(fDeltaX > 0.0 && nIntX + 1L < rRead.Width())
122 nIndX++;
124 else if(fDeltaX < 0.0 && nIntX >= 1L)
126 fDeltaX = -fDeltaX;
127 nIndX--;
130 if(fDeltaY > 0.0 && nIntY + 1L < rRead.Height())
132 nIndY++;
134 else if(fDeltaY < 0.0 && nIntY >= 1L)
136 fDeltaY = -fDeltaY;
137 nIndY--;
140 if(nIndX || nIndY)
142 const double fColorToReal(1.0 / 255.0);
143 double fVal(rValue.GetIndex() * fColorToReal);
144 double fValBottom(0.0);
146 if(nIndX)
148 const double fMulA(fDeltaX * fColorToReal);
149 double fMulB(1.0 - fDeltaX);
150 const BitmapColor aTopPartner(rRead.GetPixel(nIntY, nIntX + nIndX));
152 fVal = (fVal * fMulB) + (aTopPartner.GetIndex() * fMulA);
154 if(nIndY)
156 fMulB *= fColorToReal;
157 const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX));
158 const BitmapColor aBottomPartner(rRead.GetPixel(nIntY + nIndY, nIntX + nIndX));
160 fValBottom = (aBottom.GetIndex() * fMulB) + (aBottomPartner.GetIndex() * fMulA);
164 if(nIndY)
166 if(!nIndX)
168 const BitmapColor aBottom(rRead.GetPixel(nIntY + nIndY, nIntX));
170 fValBottom = aBottom.GetIndex() * fColorToReal;
173 const double fMulB(1.0 - fDeltaY);
175 fVal = (fVal * fMulB) + (fValBottom * fDeltaY);
178 rValue.SetIndex((sal_uInt8)(fVal * 255.0));
182 void impTransformBitmap(const Bitmap& rSource, Bitmap& rDestination, const basegfx::B2DHomMatrix& rTransform, bool bSmooth)
184 BitmapWriteAccess* pWrite = rDestination.AcquireWriteAccess();
186 if(pWrite)
188 const Size aContentSizePixel(rSource.GetSizePixel());
189 BitmapReadAccess* pRead = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
191 if(pRead)
193 const Size aDestinationSizePixel(rDestination.GetSizePixel());
194 bool bWorkWithIndex(rDestination.GetBitCount() <= 8);
195 BitmapColor aOutside(pRead->GetBestMatchingColor(BitmapColor(0xff, 0xff, 0xff)));
197 for(sal_Int32 y(0L); y < aDestinationSizePixel.getHeight(); y++)
199 for(sal_Int32 x(0L); x < aDestinationSizePixel.getWidth(); x++)
201 const basegfx::B2DPoint aSourceCoor(rTransform * basegfx::B2DPoint(x, y));
202 const sal_Int32 nIntX(basegfx::fround(aSourceCoor.getX()));
204 if(nIntX >= 0L && nIntX < aContentSizePixel.getWidth())
206 const sal_Int32 nIntY(basegfx::fround(aSourceCoor.getY()));
208 if(nIntY >= 0L && nIntY < aContentSizePixel.getHeight())
210 if(bWorkWithIndex)
212 BitmapColor aValue(pRead->GetPixel(nIntY, nIntX));
214 if(bSmooth)
216 impSmoothIndex(aValue, aSourceCoor, nIntX, nIntY, *pRead);
219 pWrite->SetPixel(y, x, aValue);
221 else
223 BitmapColor aValue(pRead->GetColor(nIntY, nIntX));
225 if(bSmooth)
227 impSmoothPoint(aValue, aSourceCoor, nIntX, nIntY, *pRead);
230 pWrite->SetPixel(y, x, aValue.IsIndex() ? aValue : pWrite->GetBestMatchingColor(aValue));
233 continue;
237 // here are outside pixels. Complete mask
238 if(bWorkWithIndex)
240 pWrite->SetPixel(y, x, aOutside);
245 delete pRead;
248 delete pWrite;
252 Bitmap impCreateEmptyBitmapWithPattern(const Bitmap& rSource, const Size& aTargetSizePixel)
254 Bitmap aRetval;
255 BitmapReadAccess* pReadAccess = (const_cast< Bitmap& >(rSource)).AcquireReadAccess();
257 if(pReadAccess)
259 if(rSource.GetBitCount() <= 8)
261 BitmapPalette aPalette(pReadAccess->GetPalette());
262 aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount(), &aPalette);
264 else
266 aRetval = Bitmap(aTargetSizePixel, rSource.GetBitCount());
269 delete pReadAccess;
272 return aRetval;
274 } // end of anonymous namespace
275 } // end of namespace drawinglayer
277 namespace drawinglayer
279 BitmapEx impTransformBitmapEx(
280 const BitmapEx& rSource,
281 const Rectangle& rCroppedRectPixel,
282 const basegfx::B2DHomMatrix& rTransform)
284 // force destination to 24 bit, we want to smooth output
285 const Size aDestinationSize(rCroppedRectPixel.GetSize());
286 Bitmap aDestination(impCreateEmptyBitmapWithPattern(rSource.GetBitmap(), aDestinationSize));
287 static bool bDoSmoothAtAll(true);
288 impTransformBitmap(rSource.GetBitmap(), aDestination, rTransform, bDoSmoothAtAll);
290 // create mask
291 if(rSource.IsTransparent())
293 if(rSource.IsAlpha())
295 Bitmap aAlpha(impCreateEmptyBitmapWithPattern(rSource.GetAlpha().GetBitmap(), aDestinationSize));
296 impTransformBitmap(rSource.GetAlpha().GetBitmap(), aAlpha, rTransform, bDoSmoothAtAll);
297 return BitmapEx(aDestination, AlphaMask(aAlpha));
299 else
301 Bitmap aMask(impCreateEmptyBitmapWithPattern(rSource.GetMask(), aDestinationSize));
302 impTransformBitmap(rSource.GetMask(), aMask, rTransform, false);
303 return BitmapEx(aDestination, aMask);
307 return BitmapEx(aDestination);
310 BitmapEx impModifyBitmapEx(
311 const basegfx::BColorModifierStack& rBColorModifierStack,
312 const BitmapEx& rSource)
314 Bitmap aChangedBitmap(rSource.GetBitmap());
315 bool bDone(false);
317 for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
319 const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
321 switch(rModifier.getMode())
323 case basegfx::BCOLORMODIFYMODE_REPLACE :
325 // complete replace
326 if(rSource.IsTransparent())
328 // clear bitmap with dest color
329 if(aChangedBitmap.GetBitCount() <= 8)
331 // do NOT use erase; for e.g. 8bit Bitmaps, the nearest color to the given
332 // erase color is determined and used -> this may be different from what is
333 // wanted here. Better create a new bitmap with the needed color explicitly
334 BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
335 OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
337 if(pReadAccess)
339 BitmapPalette aNewPalette(pReadAccess->GetPalette());
340 aNewPalette[0] = BitmapColor(Color(rModifier.getBColor()));
341 aChangedBitmap = Bitmap(
342 aChangedBitmap.GetSizePixel(),
343 aChangedBitmap.GetBitCount(),
344 &aNewPalette);
345 delete pReadAccess;
348 else
350 aChangedBitmap.Erase(Color(rModifier.getBColor()));
353 else
355 // erase bitmap, caller will know to paint direct
356 aChangedBitmap.SetEmpty();
359 bDone = true;
360 break;
363 default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
365 BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
367 if(pContent)
369 const double fConvertColor(1.0 / 255.0);
371 for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
373 for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
375 const BitmapColor aBMCol(pContent->GetColor(y, x));
376 const basegfx::BColor aBSource(
377 (double)aBMCol.GetRed() * fConvertColor,
378 (double)aBMCol.GetGreen() * fConvertColor,
379 (double)aBMCol.GetBlue() * fConvertColor);
380 const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource));
382 pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
386 delete pContent;
389 break;
394 if(aChangedBitmap.IsEmpty())
396 return BitmapEx();
398 else
400 if(rSource.IsTransparent())
402 if(rSource.IsAlpha())
404 return BitmapEx(aChangedBitmap, rSource.GetAlpha());
406 else
408 return BitmapEx(aChangedBitmap, rSource.GetMask());
411 else
413 return BitmapEx(aChangedBitmap);
417 } // end of namespace drawinglayer
419 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */