Bug Summary

File:home/maarten/src/libreoffice/core/vcl/source/bitmap/bitmap.cxx
Warning:line 606, column 95
Use of zero-allocated memory

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name bitmap.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/glm -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/libmount -isystem /usr/include/blkid -isystem /usr/include/cairo -isystem /usr/include/glib-2.0 -isystem /usr/lib64/glib-2.0/include -isystem /usr/include/pixman-1 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/libxml2 -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -isystem /usr/include/dbus-1.0 -isystem /usr/lib64/dbus-1.0/include -isystem /usr/include/freetype2 -isystem /usr/include/libpng16 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D VCL_DLLIMPLEMENTATION -D DLLIMPLEMENTATION_UITEST -D CUI_DLL_NAME="libcuilo.so" -D DESKTOP_DETECTOR_DLL_NAME="libdesktop_detectorlo.so" -D TK_DLL_NAME="libtklo.so" -D SYSTEM_ZLIB -D GLM_FORCE_CTOR_INIT -D SK_USER_CONFIG_HEADER=</home/maarten/src/libreoffice/core/config_host/config_skia.h> -D SKIA_DLL -D ENABLE_CUPS -D HAVE_VALGRIND_HEADERS -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/core -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/effects -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/config -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/ports -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/include/third_party/vulkan -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia/tools/gpu -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/skia -I /home/maarten/src/libreoffice/core/external/skia/inc/ -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/lcms2/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/harfbuzz/src -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/graphite/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libpng -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/libjpeg-turbo -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/vcl/inc -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libxml2 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/vcl/source/bitmap/bitmap.cxx
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <osl/diagnose.h>
21#include <tools/helpers.hxx>
22#include <vcl/bitmap.hxx>
23#include <vcl/bitmapaccess.hxx>
24#include <vcl/outdev.hxx>
25
26#include <svdata.hxx>
27#include <salinst.hxx>
28#include <salbmp.hxx>
29#include <bitmapwriteaccess.hxx>
30
31#include <algorithm>
32#include <memory>
33
34#ifdef DBG_UTIL
35#include <cstdlib>
36#include <tools/stream.hxx>
37#include <vcl/graphicfilter.hxx>
38#endif
39
40Bitmap::Bitmap()
41{
42}
43
44Bitmap::Bitmap(const Bitmap& rBitmap)
45 : mxSalBmp(rBitmap.mxSalBmp)
46 , maPrefMapMode(rBitmap.maPrefMapMode)
47 , maPrefSize(rBitmap.maPrefSize)
48{
49}
50
51Bitmap::Bitmap(std::shared_ptr<SalBitmap> const & pSalBitmap)
52 : mxSalBmp(pSalBitmap)
53 , maPrefMapMode(MapMode(MapUnit::MapPixel))
54 , maPrefSize(mxSalBmp->GetSize())
55{
56}
57
58Bitmap::Bitmap( const Size& rSizePixel, sal_uInt16 nBitCount, const BitmapPalette* pPal )
59{
60 if (!(rSizePixel.Width() && rSizePixel.Height()))
61 return;
62
63 BitmapPalette aPal;
64 BitmapPalette* pRealPal = nullptr;
65
66 if( nBitCount <= 8 )
67 {
68 if( !pPal )
69 {
70 if( 1 == nBitCount )
71 {
72 aPal.SetEntryCount( 2 );
73 aPal[ 0 ] = COL_BLACK;
74 aPal[ 1 ] = COL_WHITE;
75 }
76 else if( ( 4 == nBitCount ) || ( 8 == nBitCount ) )
77 {
78 aPal.SetEntryCount( 1 << nBitCount );
79 aPal[ 0 ] = COL_BLACK;
80 aPal[ 1 ] = COL_BLUE;
81 aPal[ 2 ] = COL_GREEN;
82 aPal[ 3 ] = COL_CYAN;
83 aPal[ 4 ] = COL_RED;
84 aPal[ 5 ] = COL_MAGENTA;
85 aPal[ 6 ] = COL_BROWN;
86 aPal[ 7 ] = COL_GRAY;
87 aPal[ 8 ] = COL_LIGHTGRAY;
88 aPal[ 9 ] = COL_LIGHTBLUE;
89 aPal[ 10 ] = COL_LIGHTGREEN;
90 aPal[ 11 ] = COL_LIGHTCYAN;
91 aPal[ 12 ] = COL_LIGHTRED;
92 aPal[ 13 ] = COL_LIGHTMAGENTA;
93 aPal[ 14 ] = COL_YELLOW;
94 aPal[ 15 ] = COL_WHITE;
95
96 // Create dither palette
97 if( 8 == nBitCount )
98 {
99 sal_uInt16 nActCol = 16;
100
101 for( sal_uInt16 nB = 0; nB < 256; nB += 51 )
102 for( sal_uInt16 nG = 0; nG < 256; nG += 51 )
103 for( sal_uInt16 nR = 0; nR < 256; nR += 51 )
104 aPal[ nActCol++ ] = BitmapColor( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
105
106 // Set standard Office colors
107 aPal[ nActCol++ ] = BitmapColor( 0, 184, 255 );
108 }
109 }
110 }
111 else
112 pRealPal = const_cast<BitmapPalette*>(pPal);
113 }
114
115 mxSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap();
116 mxSalBmp->Create( rSizePixel, nBitCount, pRealPal ? *pRealPal : aPal );
117}
118
119#ifdef DBG_UTIL
120
121namespace
122{
123void savePNG(const OUString& sWhere, const Bitmap& rBmp)
124{
125 SvFileStream aStream(sWhere, StreamMode::WRITE | StreamMode::TRUNC);
126 GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
127 rFilter.compressAsPNG(BitmapEx(rBmp), aStream);
128}
129}
130
131#endif
132
133Bitmap::~Bitmap()
134{
135#ifdef DBG_UTIL
136 // VCL_DUMP_BMP_PATH should be like C:/bmpDump.png or ~/bmpDump.png
137 static const OUString sDumpPath(OUString::createFromAscii(std::getenv("VCL_DUMP_BMP_PATH")));
138 // Stepping into the dtor of a bitmap you need, and setting the volatile variable to true in
139 // debugger, would dump the bitmap in question
140 static volatile bool save(false);
141 if (!sDumpPath.isEmpty() && save)
142 {
143 save = false;
144 savePNG(sDumpPath, *this);
145 }
146#endif
147}
148
149const BitmapPalette& Bitmap::GetGreyPalette( int nEntries )
150{
151 // Create greyscale palette with 2, 4, 16 or 256 entries
152 switch (nEntries)
153 {
154 case 2:
155 {
156 static const BitmapPalette aGreyPalette2 = [] {
157 BitmapPalette aPalette(2);
158 aPalette[0] = BitmapColor(0, 0, 0);
159 aPalette[1] = BitmapColor(255, 255, 255);
160 return aPalette;
161 }();
162
163 return aGreyPalette2;
164 }
165 case 4:
166 {
167 static const BitmapPalette aGreyPalette4 = [] {
168 BitmapPalette aPalette(4);
169 aPalette[0] = BitmapColor(0, 0, 0);
170 aPalette[1] = BitmapColor(85, 85, 85);
171 aPalette[2] = BitmapColor(170, 170, 170);
172 aPalette[3] = BitmapColor(255, 255, 255);
173 return aPalette;
174 }();
175
176 return aGreyPalette4;
177 }
178 case 16:
179 {
180 static const BitmapPalette aGreyPalette16 = [] {
181 sal_uInt8 cGrey = 0;
182 sal_uInt8 const cGreyInc = 17;
183
184 BitmapPalette aPalette(16);
185
186 for (sal_uInt16 i = 0; i < 16; ++i, cGrey += cGreyInc)
187 aPalette[i] = BitmapColor(cGrey, cGrey, cGrey);
188
189 return aPalette;
190 }();
191
192 return aGreyPalette16;
193 }
194 case 256:
195 {
196 static const BitmapPalette aGreyPalette256 = [] {
197 BitmapPalette aPalette(256);
198
199 for (sal_uInt16 i = 0; i < 256; ++i)
200 aPalette[i] = BitmapColor(static_cast<sal_uInt8>(i), static_cast<sal_uInt8>(i),
201 static_cast<sal_uInt8>(i));
202
203 return aPalette;
204 }();
205
206 return aGreyPalette256;
207 }
208 }
209 OSL_FAIL("Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/vcl/source/bitmap/bitmap.cxx"
":" "209" ": "), "%s", "Bitmap::GetGreyPalette: invalid entry count (2/4/16/256 allowed)"
); } } while (false)
;
210 return GetGreyPalette(2);
211}
212
213bool BitmapPalette::IsGreyPaletteAny() const
214{
215 const int nEntryCount = GetEntryCount();
216 if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
217 return true;
218 // See above: only certain entry values will result in a valid call to GetGreyPalette
219 if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 )
220 {
221 const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
222 if( rGreyPalette == *this )
223 return true;
224 }
225
226 bool bRet = false;
227 // TODO: is it worth to compare the entries for the general case?
228 if (nEntryCount == 2)
229 {
230 const BitmapColor& rCol0(maBitmapColor[0]);
231 const BitmapColor& rCol1(maBitmapColor[1]);
232 bRet = rCol0.GetRed() == rCol0.GetGreen() && rCol0.GetRed() == rCol0.GetBlue() &&
233 rCol1.GetRed() == rCol1.GetGreen() && rCol1.GetRed() == rCol1.GetBlue();
234 }
235 return bRet;
236}
237
238bool BitmapPalette::IsGreyPalette8Bit() const
239{
240 const int nEntryCount = GetEntryCount();
241 if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
242 return true;
243 if( nEntryCount != 256 )
244 return false;
245 for (sal_uInt16 i = 0; i < 256; ++i)
246 {
247 if( maBitmapColor[i] != BitmapColor(i, i, i))
248 return false;
249 }
250 return true;
251}
252
253Bitmap& Bitmap::operator=( const Bitmap& rBitmap )
254{
255 if (this == &rBitmap)
256 return *this;
257
258 maPrefSize = rBitmap.maPrefSize;
259 maPrefMapMode = rBitmap.maPrefMapMode;
260 mxSalBmp = rBitmap.mxSalBmp;
261
262 return *this;
263}
264
265Bitmap& Bitmap::operator=( Bitmap&& rBitmap ) noexcept
266{
267 maPrefSize = std::move(rBitmap.maPrefSize);
268 maPrefMapMode = std::move(rBitmap.maPrefMapMode);
269 mxSalBmp = std::move(rBitmap.mxSalBmp);
270
271 return *this;
272}
273
274bool Bitmap::operator==( const Bitmap& rBmp ) const
275{
276 if (rBmp.mxSalBmp == mxSalBmp) // Includes both are nullptr
277 return true;
278 if (!rBmp.mxSalBmp || !mxSalBmp)
279 return false;
280 if (rBmp.mxSalBmp->GetSize() != mxSalBmp->GetSize() ||
281 rBmp.mxSalBmp->GetBitCount() != mxSalBmp->GetBitCount())
282 return false;
283 BitmapChecksum aChecksum1, aChecksum2;
284 rBmp.mxSalBmp->GetChecksum(aChecksum1);
285 mxSalBmp->GetChecksum(aChecksum2);
286 // If the bitmaps can't calculate a checksum, best to regard them as different.
287 if (aChecksum1 == 0 || aChecksum2 == 0)
288 return false;
289 return aChecksum1 == aChecksum2;
290}
291
292void Bitmap::SetEmpty()
293{
294 maPrefMapMode = MapMode();
295 maPrefSize = Size();
296 mxSalBmp.reset();
297}
298
299Size Bitmap::GetSizePixel() const
300{
301 return( mxSalBmp ? mxSalBmp->GetSize() : Size() );
302}
303
304sal_uInt16 Bitmap::GetBitCount() const
305{
306 if (!mxSalBmp)
307 return 0;
308
309 sal_uInt16 nBitCount = mxSalBmp->GetBitCount();
310 if (nBitCount <= 1)
311 return 1;
312 if (nBitCount <= 4)
313 return 4;
314 if (nBitCount <= 8)
315 return 8;
316 if (nBitCount <= 24)
317 return 24;
318 if (nBitCount <= 32)
319 return 32;
320 return 0;
321}
322
323bool Bitmap::HasGreyPaletteAny() const
324{
325 const sal_uInt16 nBitCount = GetBitCount();
326 bool bRet = nBitCount == 1;
327
328 ScopedInfoAccess pIAcc(const_cast<Bitmap&>(*this));
329
330 if( pIAcc )
331 {
332 bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPaletteAny();
333 }
334
335 return bRet;
336}
337
338bool Bitmap::HasGreyPalette8Bit() const
339{
340 bool bRet = false;
341 ScopedInfoAccess pIAcc(const_cast<Bitmap&>(*this));
342
343 if( pIAcc )
344 {
345 bRet = pIAcc->HasPalette() && pIAcc->GetPalette().IsGreyPalette8Bit();
346 }
347
348 return bRet;
349}
350
351BitmapChecksum Bitmap::GetChecksum() const
352{
353 BitmapChecksum nRet = 0;
354
355 if( mxSalBmp )
356 {
357 mxSalBmp->GetChecksum(nRet);
358
359 if (!nRet)
360 {
361 // nRet == 0 => probably, we were not able to acquire
362 // the buffer in SalBitmap::updateChecksum;
363 // so, we need to update the imp bitmap for this bitmap instance
364 // as we do in BitmapInfoAccess::ImplCreate
365 std::shared_ptr<SalBitmap> xNewImpBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
366 if (xNewImpBmp->Create(*mxSalBmp, GetBitCount()))
367 {
368 Bitmap* pThis = const_cast<Bitmap*>(this);
369 pThis->mxSalBmp = xNewImpBmp;
370 mxSalBmp->GetChecksum(nRet);
371 }
372 }
373 }
374
375 return nRet;
376}
377
378void Bitmap::ImplMakeUnique()
379{
380 if (mxSalBmp && mxSalBmp.use_count() > 1)
381 {
382 std::shared_ptr<SalBitmap> xOldImpBmp = mxSalBmp;
383 mxSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap();
384 (void)mxSalBmp->Create(*xOldImpBmp);
385 }
386}
387
388void Bitmap::ReassignWithSize(const Bitmap& rBitmap)
389{
390 const Size aOldSizePix(GetSizePixel());
391 const Size aNewSizePix(rBitmap.GetSizePixel());
392 const MapMode aOldMapMode(maPrefMapMode);
393 Size aNewPrefSize;
394
395 if ((aOldSizePix != aNewSizePix) && aOldSizePix.Width() && aOldSizePix.Height())
396 {
397 aNewPrefSize.setWidth(FRound(maPrefSize.Width() * aNewSizePix.Width() / aOldSizePix.Width()));
398 aNewPrefSize.setHeight(FRound(maPrefSize.Height() * aNewSizePix.Height() / aOldSizePix.Height()));
399 }
400 else
401 {
402 aNewPrefSize = maPrefSize;
403 }
404
405 *this = rBitmap;
406
407 maPrefSize = aNewPrefSize;
408 maPrefMapMode = aOldMapMode;
409}
410
411
412void Bitmap::ImplSetSalBitmap(const std::shared_ptr<SalBitmap>& xImpBmp)
413{
414 mxSalBmp = xImpBmp;
415}
416
417BitmapInfoAccess* Bitmap::AcquireInfoAccess()
418{
419 std::unique_ptr<BitmapInfoAccess> pInfoAccess(new BitmapInfoAccess( *this ));
420
421 if( !*pInfoAccess )
422 {
423 return nullptr;
424 }
425
426 return pInfoAccess.release();
427}
428
429BitmapReadAccess* Bitmap::AcquireReadAccess()
430{
431 std::unique_ptr<BitmapReadAccess> pReadAccess(new BitmapReadAccess( *this ));
432
433 if( !*pReadAccess )
434 {
435 return nullptr;
436 }
437
438 return pReadAccess.release();
439}
440
441BitmapWriteAccess* Bitmap::AcquireWriteAccess()
442{
443 std::unique_ptr<BitmapWriteAccess> pWriteAccess(new BitmapWriteAccess( *this ));
444
445 if( !*pWriteAccess )
446 {
447 return nullptr;
448 }
449
450 return pWriteAccess.release();
451}
452
453void Bitmap::ReleaseAccess( BitmapInfoAccess* pBitmapAccess )
454{
455 delete pBitmapAccess;
456}
457
458bool Bitmap::Crop( const tools::Rectangle& rRectPixel )
459{
460 const Size aSizePix( GetSizePixel() );
461 tools::Rectangle aRect( rRectPixel );
462 bool bRet = false;
463
464 aRect.Intersection( tools::Rectangle( Point(), aSizePix ) );
465
466 if( !aRect.IsEmpty() && aSizePix != aRect.GetSize())
467 {
468 ScopedReadAccess pReadAcc(*this);
469
470 if( pReadAcc )
471 {
472 const tools::Rectangle aNewRect( Point(), aRect.GetSize() );
473 Bitmap aNewBmp( aNewRect.GetSize(), GetBitCount(), &pReadAcc->GetPalette() );
474 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
475
476 if( pWriteAcc )
477 {
478 const long nOldX = aRect.Left();
479 const long nOldY = aRect.Top();
480 const long nNewWidth = aNewRect.GetWidth();
481 const long nNewHeight = aNewRect.GetHeight();
482
483 for( long nY = 0, nY2 = nOldY; nY < nNewHeight; nY++, nY2++ )
484 {
485 Scanline pScanline = pWriteAcc->GetScanline(nY);
486 Scanline pScanlineRead = pReadAcc->GetScanline(nY2);
487 for( long nX = 0, nX2 = nOldX; nX < nNewWidth; nX++, nX2++ )
488 pWriteAcc->SetPixelOnData( pScanline, nX, pReadAcc->GetPixelFromData( pScanlineRead, nX2 ) );
489 }
490
491 pWriteAcc.reset();
492 bRet = true;
493 }
494
495 pReadAcc.reset();
496
497 if( bRet )
498 ReassignWithSize( aNewBmp );
499 }
500 }
501
502 return bRet;
503};
504
505bool Bitmap::CopyPixel( const tools::Rectangle& rRectDst,
506 const tools::Rectangle& rRectSrc, const Bitmap* pBmpSrc )
507{
508 const Size aSizePix( GetSizePixel() );
509 tools::Rectangle aRectDst( rRectDst );
510 bool bRet = false;
511
512 aRectDst.Intersection( tools::Rectangle( Point(), aSizePix ) );
513
514 if( !aRectDst.IsEmpty() )
1
Taking true branch
515 {
516 if( pBmpSrc && ( pBmpSrc->mxSalBmp != mxSalBmp ) )
2
Assuming 'pBmpSrc' is non-null
3
Taking true branch
517 {
518 Bitmap* pSrc = const_cast<Bitmap*>(pBmpSrc);
519 const Size aCopySizePix( pSrc->GetSizePixel() );
520 tools::Rectangle aRectSrc( rRectSrc );
521 const sal_uInt16 nSrcBitCount = pBmpSrc->GetBitCount();
522 const sal_uInt16 nDstBitCount = GetBitCount();
523
524 if( nSrcBitCount
3.1
'nSrcBitCount' is <= 'nDstBitCount'
> nDstBitCount )
4
Taking false branch
525 {
526 int nNextIndex = 0;
527
528 if (nSrcBitCount == 24)
529 Convert( BmpConversion::N24Bit );
530 else if (nSrcBitCount == 8)
531 {
532 Convert( BmpConversion::N8BitColors );
533 nNextIndex = 16;
534 }
535 else if (nSrcBitCount == 4)
536 {
537 Convert( BmpConversion::N4BitColors );
538 nNextIndex = 2;
539 }
540
541 if( nNextIndex )
542 {
543 ScopedReadAccess pSrcAcc(*pSrc);
544 BitmapScopedWriteAccess pDstAcc(*this);
545
546 if( pSrcAcc && pDstAcc )
547 {
548 const int nSrcCount = pDstAcc->GetPaletteEntryCount();
549 const int nDstCount = 1 << nDstBitCount;
550
551 for (int i = 0; ( i < nSrcCount ) && ( nNextIndex < nSrcCount ); ++i)
552 {
553 const BitmapColor& rSrcCol = pSrcAcc->GetPaletteColor( static_cast<sal_uInt16>(i) );
554
555 bool bFound = false;
556
557 for (int j = 0; j < nDstCount; ++j)
558 {
559 if( rSrcCol == pDstAcc->GetPaletteColor( static_cast<sal_uInt16>(j) ) )
560 {
561 bFound = true;
562 break;
563 }
564 }
565
566 if( !bFound )
567 pDstAcc->SetPaletteColor( static_cast<sal_uInt16>(nNextIndex++), rSrcCol );
568 }
569 }
570 }
571 }
572
573 aRectSrc.Intersection( tools::Rectangle( Point(), aCopySizePix ) );
574
575 if( !aRectSrc.IsEmpty() )
5
Taking true branch
576 {
577 ScopedReadAccess pReadAcc(*pSrc);
578
579 if( pReadAcc )
6
Taking true branch
580 {
581 BitmapScopedWriteAccess pWriteAcc(*this);
582
583 if( pWriteAcc )
7
Taking true branch
584 {
585 const long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
586 const long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
587 const long nSrcEndX = aRectSrc.Left() + nWidth;
588 const long nSrcEndY = aRectSrc.Top() + nHeight;
589 long nDstY = aRectDst.Top();
590
591 if( pReadAcc->HasPalette() && pWriteAcc->HasPalette() )
8
Taking true branch
592 {
593 const sal_uInt16 nCount = pReadAcc->GetPaletteEntryCount();
594 std::unique_ptr<sal_uInt8[]> pMap(new sal_uInt8[ nCount ]);
9
Memory is allocated
595
596 // Create index map for the color table, as the bitmap should be copied
597 // retaining it's color information relatively well
598 for( sal_uInt16 i = 0; i < nCount; i++ )
10
Loop condition is false. Execution continues on line 601
599 pMap[ i ] = static_cast<sal_uInt8>(pWriteAcc->GetBestPaletteIndex( pReadAcc->GetPaletteColor( i ) ));
600
601 for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
11
Assuming 'nSrcY' is < 'nSrcEndY'
12
Loop condition is true. Entering loop body
602 {
603 Scanline pScanline = pWriteAcc->GetScanline(nDstY);
604 Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
605 for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
13
Assuming 'nSrcX' is < 'nSrcEndX'
14
Loop condition is true. Entering loop body
606 pWriteAcc->SetPixelOnData( pScanline, nDstX, BitmapColor( pMap[ pReadAcc->GetIndexFromData( pScanlineRead, nSrcX ) ] ));
15
Use of zero-allocated memory
607 }
608 }
609 else if( pReadAcc->HasPalette() )
610 {
611 for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
612 {
613 Scanline pScanline = pWriteAcc->GetScanline(nDstY);
614 Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
615 for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
616 pWriteAcc->SetPixelOnData( pScanline, nDstX, pReadAcc->GetPaletteColor( pReadAcc->GetIndexFromData( pScanlineRead, nSrcX ) ) );
617 }
618 }
619 else
620 for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++ )
621 {
622 Scanline pScanline = pWriteAcc->GetScanline(nDstY);
623 Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
624 for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
625 pWriteAcc->SetPixelOnData( pScanline, nDstX, pReadAcc->GetPixelFromData( pScanlineRead, nSrcX ) );
626 }
627
628 pWriteAcc.reset();
629 bRet = ( nWidth > 0 ) && ( nHeight > 0 );
630 }
631
632 pReadAcc.reset();
633 }
634 }
635 }
636 else
637 {
638 tools::Rectangle aRectSrc( rRectSrc );
639
640 aRectSrc.Intersection( tools::Rectangle( Point(), aSizePix ) );
641
642 if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
643 {
644 BitmapScopedWriteAccess pWriteAcc(*this);
645
646 if( pWriteAcc )
647 {
648 const long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
649 const long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
650 const long nSrcX = aRectSrc.Left();
651 const long nSrcY = aRectSrc.Top();
652 const long nSrcEndX1 = nSrcX + nWidth - 1;
653 const long nSrcEndY1 = nSrcY + nHeight - 1;
654 const long nDstX = aRectDst.Left();
655 const long nDstY = aRectDst.Top();
656 const long nDstEndX1 = nDstX + nWidth - 1;
657 const long nDstEndY1 = nDstY + nHeight - 1;
658
659 if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
660 {
661 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
662 {
663 Scanline pScanline = pWriteAcc->GetScanline(nYN);
664 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
665 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
666 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
667 }
668 }
669 else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
670 {
671 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
672 {
673 Scanline pScanline = pWriteAcc->GetScanline(nYN);
674 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
675 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
676 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
677 }
678 }
679 else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
680 {
681 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
682 {
683 Scanline pScanline = pWriteAcc->GetScanline(nYN);
684 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
685 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
686 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
687 }
688 }
689 else
690 {
691 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
692 {
693 Scanline pScanline = pWriteAcc->GetScanline(nYN);
694 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
695 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
696 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
697 }
698 }
699
700 pWriteAcc.reset();
701 bRet = true;
702 }
703 }
704 }
705 }
706
707 return bRet;
708}
709
710bool Bitmap::CopyPixel_AlphaOptimized( const tools::Rectangle& rRectDst, const tools::Rectangle& rRectSrc,
711 const Bitmap* pBmpSrc )
712{
713 // Note: this code is copied from Bitmap::CopyPixel but avoids any palette lookups
714 // This optimization is possible because the palettes of AlphaMasks are always identical (8bit GreyPalette, see ctor)
715 const Size aSizePix( GetSizePixel() );
716 tools::Rectangle aRectDst( rRectDst );
717 bool bRet = false;
718
719 aRectDst.Intersection( tools::Rectangle( Point(), aSizePix ) );
720
721 if( !aRectDst.IsEmpty() )
722 {
723 if( pBmpSrc && ( pBmpSrc->mxSalBmp != mxSalBmp ) )
724 {
725 Bitmap* pSrc = const_cast<Bitmap*>(pBmpSrc);
726 const Size aCopySizePix( pSrc->GetSizePixel() );
727 tools::Rectangle aRectSrc( rRectSrc );
728
729 aRectSrc.Intersection( tools::Rectangle( Point(), aCopySizePix ) );
730
731 if( !aRectSrc.IsEmpty() )
732 {
733 ScopedReadAccess pReadAcc(*pSrc);
734
735 if( pReadAcc )
736 {
737 BitmapScopedWriteAccess pWriteAcc(*this);
738
739 if( pWriteAcc )
740 {
741 const long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
742 const long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
743 const long nSrcEndX = aRectSrc.Left() + nWidth;
744 const long nSrcEndY = aRectSrc.Top() + nHeight;
745 long nDstY = aRectDst.Top();
746
747 for( long nSrcY = aRectSrc.Top(); nSrcY < nSrcEndY; nSrcY++, nDstY++)
748 {
749 Scanline pScanline = pWriteAcc->GetScanline(nDstY);
750 Scanline pScanlineRead = pReadAcc->GetScanline(nSrcY);
751 for( long nSrcX = aRectSrc.Left(), nDstX = aRectDst.Left(); nSrcX < nSrcEndX; nSrcX++, nDstX++ )
752 pWriteAcc->SetPixelOnData( pScanline, nDstX, pReadAcc->GetPixelFromData( pScanlineRead, nSrcX ) );
753 }
754
755 pWriteAcc.reset();
756 bRet = ( nWidth > 0 ) && ( nHeight > 0 );
757 }
758
759 pReadAcc.reset();
760 }
761 }
762 }
763 else
764 {
765 tools::Rectangle aRectSrc( rRectSrc );
766
767 aRectSrc.Intersection( tools::Rectangle( Point(), aSizePix ) );
768
769 if( !aRectSrc.IsEmpty() && ( aRectSrc != aRectDst ) )
770 {
771 BitmapScopedWriteAccess pWriteAcc(*this);
772
773 if( pWriteAcc )
774 {
775 const long nWidth = std::min( aRectSrc.GetWidth(), aRectDst.GetWidth() );
776 const long nHeight = std::min( aRectSrc.GetHeight(), aRectDst.GetHeight() );
777 const long nSrcX = aRectSrc.Left();
778 const long nSrcY = aRectSrc.Top();
779 const long nSrcEndX1 = nSrcX + nWidth - 1;
780 const long nSrcEndY1 = nSrcY + nHeight - 1;
781 const long nDstX = aRectDst.Left();
782 const long nDstY = aRectDst.Top();
783 const long nDstEndX1 = nDstX + nWidth - 1;
784 const long nDstEndY1 = nDstY + nHeight - 1;
785
786 if( ( nDstX <= nSrcX ) && ( nDstY <= nSrcY ) )
787 {
788 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
789 {
790 Scanline pScanline = pWriteAcc->GetScanline(nYN);
791 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
792 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
793 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
794 }
795 }
796 else if( ( nDstX <= nSrcX ) && ( nDstY >= nSrcY ) )
797 {
798 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
799 {
800 Scanline pScanline = pWriteAcc->GetScanline(nYN);
801 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
802 for( long nX = nSrcX, nXN = nDstX; nX <= nSrcEndX1; nX++, nXN++ )
803 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
804 }
805 }
806 else if( ( nDstX >= nSrcX ) && ( nDstY <= nSrcY ) )
807 {
808 for( long nY = nSrcY, nYN = nDstY; nY <= nSrcEndY1; nY++, nYN++ )
809 {
810 Scanline pScanline = pWriteAcc->GetScanline(nYN);
811 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
812 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
813 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
814 }
815 }
816 else
817 {
818 for( long nY = nSrcEndY1, nYN = nDstEndY1; nY >= nSrcY; nY--, nYN-- )
819 {
820 Scanline pScanline = pWriteAcc->GetScanline(nYN);
821 Scanline pScanlineSrc = pWriteAcc->GetScanline(nY);
822 for( long nX = nSrcEndX1, nXN = nDstEndX1; nX >= nSrcX; nX--, nXN-- )
823 pWriteAcc->SetPixelOnData( pScanline, nXN, pWriteAcc->GetPixelFromData( pScanlineSrc, nX ) );
824 }
825 }
826
827 pWriteAcc.reset();
828 bRet = true;
829 }
830 }
831 }
832 }
833
834 return bRet;
835
836}
837
838bool Bitmap::Expand( sal_uLong nDX, sal_uLong nDY, const Color* pInitColor )
839{
840 bool bRet = false;
841
842 if( nDX || nDY )
843 {
844 const Size aSizePixel( GetSizePixel() );
845 const long nWidth = aSizePixel.Width();
846 const long nHeight = aSizePixel.Height();
847 const Size aNewSize( nWidth + nDX, nHeight + nDY );
848 ScopedReadAccess pReadAcc(*this);
849
850 if( pReadAcc )
851 {
852 BitmapPalette aBmpPal( pReadAcc->GetPalette() );
853 Bitmap aNewBmp( aNewSize, GetBitCount(), &aBmpPal );
854 BitmapScopedWriteAccess pWriteAcc(aNewBmp);
855
856 if( pWriteAcc )
857 {
858 BitmapColor aColor;
859 const long nNewX = nWidth;
860 const long nNewY = nHeight;
861 const long nNewWidth = pWriteAcc->Width();
862 const long nNewHeight = pWriteAcc->Height();
863 long nX;
864 long nY;
865
866 if( pInitColor )
867 aColor = pWriteAcc->GetBestMatchingColor( *pInitColor );
868
869 for( nY = 0; nY < nHeight; nY++ )
870 {
871 pWriteAcc->CopyScanline( nY, *pReadAcc );
872
873 if( pInitColor && nDX )
874 {
875 Scanline pScanline = pWriteAcc->GetScanline(nY);
876 for( nX = nNewX; nX < nNewWidth; nX++ )
877 pWriteAcc->SetPixelOnData( pScanline, nX, aColor );
878 }
879 }
880
881 if( pInitColor && nDY )
882 for( nY = nNewY; nY < nNewHeight; nY++ )
883 {
884 Scanline pScanline = pWriteAcc->GetScanline(nY);
885 for( nX = 0; nX < nNewWidth; nX++ )
886 pWriteAcc->SetPixelOnData( pScanline, nX, aColor );
887 }
888
889 pWriteAcc.reset();
890 bRet = true;
891 }
892
893 pReadAcc.reset();
894
895 if (bRet)
896 ReassignWithSize(aNewBmp);
897 }
898 }
899
900 return bRet;
901}
902
903Bitmap Bitmap::CreateDisplayBitmap( OutputDevice* pDisplay ) const
904{
905 Bitmap aDispBmp( *this );
906
907 SalGraphics* pDispGraphics = pDisplay->GetGraphics();
908
909 if( mxSalBmp && pDispGraphics )
910 {
911 std::shared_ptr<SalBitmap> xImpDispBmp(ImplGetSVData()->mpDefInst->CreateSalBitmap());
912 if (xImpDispBmp->Create(*mxSalBmp, pDispGraphics))
913 aDispBmp.ImplSetSalBitmap(xImpDispBmp);
914 }
915
916 return aDispBmp;
917}
918
919bool Bitmap::GetSystemData( BitmapSystemData& rData ) const
920{
921 return mxSalBmp && mxSalBmp->GetSystemData(rData);
922}
923
924/* vim:set shiftwidth=4 softtabstop=4 expandtab: */