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 <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include <cstring>
24
25 #include <headless/svpbmp.hxx>
26 #include <headless/svpgdi.hxx>
27 #include <headless/svpinst.hxx>
28
29 #include <basegfx/vector/b2ivector.hxx>
30 #include <basegfx/range/b2ibox.hxx>
31 #include <o3tl/safeint.hxx>
32 #include <tools/helpers.hxx>
33 #include <vcl/bitmap.hxx>
34
35 using namespace basegfx;
36
SvpSalBitmap()37 SvpSalBitmap::SvpSalBitmap()
38 : SalBitmap(),
39 basegfx::SystemDependentDataHolder(), // MM02
40 mpDIB()
41 {
42 }
43
~SvpSalBitmap()44 SvpSalBitmap::~SvpSalBitmap()
45 {
46 Destroy();
47 }
48
ImplCreateDIB(const Size & rSize,vcl::PixelFormat ePixelFormat,const BitmapPalette & rPal)49 static std::unique_ptr<BitmapBuffer> ImplCreateDIB(
50 const Size& rSize,
51 vcl::PixelFormat ePixelFormat,
52 const BitmapPalette& rPal)
53 {
54 if (!rSize.Width() || !rSize.Height())
55 return nullptr;
56
57 std::unique_ptr<BitmapBuffer> pDIB;
58
59 try
60 {
61 pDIB.reset(new BitmapBuffer);
62 }
63 catch (const std::bad_alloc&)
64 {
65 return nullptr;
66 }
67
68 switch (ePixelFormat)
69 {
70 case vcl::PixelFormat::N1_BPP:
71 pDIB->mnFormat = ScanlineFormat::N1BitLsbPal;
72 break;
73 case vcl::PixelFormat::N8_BPP:
74 pDIB->mnFormat = ScanlineFormat::N8BitPal;
75 break;
76 case vcl::PixelFormat::N24_BPP:
77 pDIB->mnFormat = SVP_24BIT_FORMAT;
78 break;
79 case vcl::PixelFormat::N32_BPP:
80 pDIB->mnFormat = SVP_CAIRO_FORMAT;
81 break;
82 case vcl::PixelFormat::INVALID:
83 assert(false);
84 pDIB->mnFormat = SVP_CAIRO_FORMAT;
85 break;
86 }
87
88 sal_uInt16 nColors = 0;
89 if (ePixelFormat <= vcl::PixelFormat::N8_BPP)
90 nColors = vcl::numberOfColors(ePixelFormat);
91
92 pDIB->mnFormat |= ScanlineFormat::TopDown;
93 pDIB->mnWidth = rSize.Width();
94 pDIB->mnHeight = rSize.Height();
95 tools::Long nScanlineBase;
96 bool bFail = o3tl::checked_multiply<tools::Long>(pDIB->mnWidth, vcl::pixelFormatBitCount(ePixelFormat), nScanlineBase);
97 if (bFail)
98 {
99 SAL_WARN("vcl.gdi", "checked multiply failed");
100 return nullptr;
101 }
102 pDIB->mnScanlineSize = AlignedWidth4Bytes(nScanlineBase);
103 if (pDIB->mnScanlineSize < nScanlineBase/8)
104 {
105 SAL_WARN("vcl.gdi", "scanline calculation wraparound");
106 return nullptr;
107 }
108 pDIB->mnBitCount = vcl::pixelFormatBitCount(ePixelFormat);
109
110 if (nColors)
111 {
112 pDIB->maPalette = rPal;
113 pDIB->maPalette.SetEntryCount( nColors );
114 }
115
116 size_t size;
117 bFail = o3tl::checked_multiply<size_t>(pDIB->mnHeight, pDIB->mnScanlineSize, size);
118 SAL_WARN_IF(bFail, "vcl.gdi", "checked multiply failed");
119 if (bFail || size > SAL_MAX_INT32/2)
120 {
121 return nullptr;
122 }
123
124 try
125 {
126 pDIB->mpBits = new sal_uInt8[size];
127 #ifdef __SANITIZE_ADDRESS__
128 if (!pDIB->mpBits)
129 { // can only happen with ASAN allocator_may_return_null=1
130 pDIB.reset();
131 }
132 else
133 #endif
134 {
135 std::memset(pDIB->mpBits, 0, size);
136 }
137 }
138 catch (const std::bad_alloc&)
139 {
140 pDIB.reset();
141 }
142
143 return pDIB;
144 }
145
Create(std::unique_ptr<BitmapBuffer> pBuf)146 void SvpSalBitmap::Create(std::unique_ptr<BitmapBuffer> pBuf)
147 {
148 Destroy();
149 mpDIB = std::move(pBuf);
150 }
151
Create(const Size & rSize,vcl::PixelFormat ePixelFormat,const BitmapPalette & rPal)152 bool SvpSalBitmap::Create(const Size& rSize, vcl::PixelFormat ePixelFormat, const BitmapPalette& rPal)
153 {
154 Destroy();
155 mpDIB = ImplCreateDIB(rSize, ePixelFormat, rPal);
156 return mpDIB != nullptr;
157 }
158
Create(const SalBitmap & rBmp)159 bool SvpSalBitmap::Create(const SalBitmap& rBmp)
160 {
161 Destroy();
162
163 const SvpSalBitmap& rSalBmp = static_cast<const SvpSalBitmap&>(rBmp);
164
165 if (rSalBmp.mpDIB)
166 {
167 // TODO: reference counting...
168 mpDIB.reset(new BitmapBuffer( *rSalBmp.mpDIB ));
169
170 const size_t size = mpDIB->mnScanlineSize * mpDIB->mnHeight;
171 if (size > SAL_MAX_INT32/2)
172 {
173 mpDIB.reset();
174 return false;
175 }
176
177 // TODO: get rid of this when BitmapBuffer gets copy constructor
178 try
179 {
180 mpDIB->mpBits = new sal_uInt8[size];
181 std::memcpy(mpDIB->mpBits, rSalBmp.mpDIB->mpBits, size);
182 }
183 catch (const std::bad_alloc&)
184 {
185 mpDIB.reset();
186 }
187 }
188
189 return !rSalBmp.mpDIB || (mpDIB != nullptr);
190 }
191
Create(const SalBitmap &,SalGraphics *)192 bool SvpSalBitmap::Create( const SalBitmap& /*rSalBmp*/,
193 SalGraphics* /*pGraphics*/ )
194 {
195 return false;
196 }
197
Create(const SalBitmap &,vcl::PixelFormat)198 bool SvpSalBitmap::Create(const SalBitmap& /*rSalBmp*/,
199 vcl::PixelFormat /*eNewPixelFormat*/)
200 {
201 return false;
202 }
203
Create(const css::uno::Reference<css::rendering::XBitmapCanvas> &,Size &,bool)204 bool SvpSalBitmap::Create( const css::uno::Reference< css::rendering::XBitmapCanvas >& /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ )
205 {
206 return false;
207 }
208
Destroy()209 void SvpSalBitmap::Destroy()
210 {
211 if (mpDIB)
212 {
213 delete[] mpDIB->mpBits;
214 mpDIB.reset();
215 }
216 }
217
GetSize() const218 Size SvpSalBitmap::GetSize() const
219 {
220 Size aSize;
221
222 if (mpDIB)
223 {
224 aSize.setWidth( mpDIB->mnWidth );
225 aSize.setHeight( mpDIB->mnHeight );
226 }
227
228 return aSize;
229 }
230
GetBitCount() const231 sal_uInt16 SvpSalBitmap::GetBitCount() const
232 {
233 sal_uInt16 nBitCount;
234
235 if (mpDIB)
236 nBitCount = mpDIB->mnBitCount;
237 else
238 nBitCount = 0;
239
240 return nBitCount;
241 }
242
AcquireBuffer(BitmapAccessMode)243 BitmapBuffer* SvpSalBitmap::AcquireBuffer(BitmapAccessMode)
244 {
245 return mpDIB.get();
246 }
247
ReleaseBuffer(BitmapBuffer *,BitmapAccessMode nMode)248 void SvpSalBitmap::ReleaseBuffer(BitmapBuffer*, BitmapAccessMode nMode)
249 {
250 if( nMode == BitmapAccessMode::Write )
251 InvalidateChecksum();
252 }
253
GetSystemData(BitmapSystemData &)254 bool SvpSalBitmap::GetSystemData( BitmapSystemData& )
255 {
256 return false;
257 }
258
ScalingSupported() const259 bool SvpSalBitmap::ScalingSupported() const
260 {
261 return false;
262 }
263
Scale(const double &,const double &,BmpScaleFlag)264 bool SvpSalBitmap::Scale( const double& /*rScaleX*/, const double& /*rScaleY*/, BmpScaleFlag /*nScaleFlag*/ )
265 {
266 return false;
267 }
268
Replace(const::Color &,const::Color &,sal_uInt8)269 bool SvpSalBitmap::Replace( const ::Color& /*rSearchColor*/, const ::Color& /*rReplaceColor*/, sal_uInt8 /*nTol*/ )
270 {
271 return false;
272 }
273
274 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
275