/src/libreoffice/vcl/headless/svpbmp.cxx
Line | Count | Source |
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 | | #include <headless/svpbmp.hxx> |
25 | | #include <o3tl/safeint.hxx> |
26 | | #include <tools/helpers.hxx> |
27 | | #include <vcl/bitmap.hxx> |
28 | | #include <vcl/CairoFormats.hxx> |
29 | | |
30 | | using namespace basegfx; |
31 | | |
32 | | SvpSalBitmap::SvpSalBitmap() |
33 | 717k | { |
34 | 717k | } |
35 | | |
36 | | SvpSalBitmap::~SvpSalBitmap() |
37 | 717k | { |
38 | 717k | Destroy(); |
39 | 717k | } |
40 | | |
41 | | static std::optional<BitmapBuffer> ImplCreateDIB( |
42 | | const Size& rSize, |
43 | | vcl::PixelFormat ePixelFormat, |
44 | | const BitmapPalette& rPal, |
45 | | bool bClear, |
46 | | bool bWithoutAlpha) |
47 | 610k | { |
48 | 610k | if (!rSize.Width() || !rSize.Height()) |
49 | 0 | return std::nullopt; |
50 | | |
51 | 610k | std::optional<BitmapBuffer> pDIB(std::in_place); |
52 | | |
53 | 610k | switch (ePixelFormat) |
54 | 610k | { |
55 | 177k | case vcl::PixelFormat::N8_BPP: |
56 | 177k | pDIB->meFormat = ScanlineFormat::N8BitPal; |
57 | 177k | break; |
58 | 372k | case vcl::PixelFormat::N24_BPP: |
59 | 372k | pDIB->meFormat = SVP_24BIT_FORMAT; |
60 | 372k | break; |
61 | 60.0k | case vcl::PixelFormat::N32_BPP: |
62 | | #if ENABLE_CAIRO_RGBA |
63 | | pDIB->meFormat = bWithoutAlpha ? ScanlineFormat::N32BitTcRgbx : SVP_CAIRO_FORMAT; |
64 | | #elif defined OSL_BIGENDIAN |
65 | | pDIB->meFormat = bWithoutAlpha ? ScanlineFormat::N32BitTcXrgb : SVP_CAIRO_FORMAT; |
66 | | #else |
67 | 60.0k | pDIB->meFormat = bWithoutAlpha ? ScanlineFormat::N32BitTcBgrx : SVP_CAIRO_FORMAT; |
68 | 60.0k | #endif |
69 | 60.0k | break; |
70 | 0 | case vcl::PixelFormat::INVALID: |
71 | 0 | assert(false); |
72 | 0 | pDIB->meFormat = SVP_CAIRO_FORMAT; |
73 | 0 | break; |
74 | 610k | } |
75 | | |
76 | 610k | sal_uInt16 nColors = 0; |
77 | 610k | if (ePixelFormat <= vcl::PixelFormat::N8_BPP) |
78 | 177k | nColors = vcl::numberOfColors(ePixelFormat); |
79 | | |
80 | 610k | pDIB->meDirection = ScanlineDirection::TopDown; |
81 | 610k | pDIB->mnWidth = rSize.Width(); |
82 | 610k | pDIB->mnHeight = rSize.Height(); |
83 | 610k | tools::Long nScanlineBase; |
84 | 610k | bool bFail = o3tl::checked_multiply<tools::Long>(pDIB->mnWidth, vcl::pixelFormatBitCount(ePixelFormat), nScanlineBase); |
85 | 610k | if (bFail) |
86 | 0 | { |
87 | 0 | SAL_WARN("vcl.gdi", "checked multiply failed"); |
88 | 0 | return std::nullopt; |
89 | 0 | } |
90 | 610k | pDIB->mnScanlineSize = AlignedWidth4Bytes(nScanlineBase); |
91 | 610k | if (pDIB->mnScanlineSize < nScanlineBase/8) |
92 | 13 | { |
93 | 13 | SAL_WARN("vcl.gdi", "scanline calculation wraparound"); |
94 | 13 | return std::nullopt; |
95 | 13 | } |
96 | 610k | pDIB->mnBitCount = vcl::pixelFormatBitCount(ePixelFormat); |
97 | | |
98 | 610k | if (nColors) |
99 | 177k | { |
100 | 177k | pDIB->maPalette = rPal; |
101 | 177k | pDIB->maPalette.SetEntryCount( nColors ); |
102 | 177k | } |
103 | | |
104 | 610k | size_t size; |
105 | 610k | bFail = o3tl::checked_multiply<size_t>(pDIB->mnHeight, pDIB->mnScanlineSize, size); |
106 | 610k | SAL_WARN_IF(bFail, "vcl.gdi", "checked multiply failed"); |
107 | 610k | if (bFail || size > SAL_MAX_INT32/2) |
108 | 155 | { |
109 | 155 | return std::nullopt; |
110 | 155 | } |
111 | | |
112 | 610k | try |
113 | 610k | { |
114 | 610k | pDIB->mpBits = new sal_uInt8[size]; |
115 | | #ifdef __SANITIZE_ADDRESS__ |
116 | | if (!pDIB->mpBits) |
117 | | { // can only happen with ASAN allocator_may_return_null=1 |
118 | | pDIB.reset(); |
119 | | } |
120 | | else |
121 | | #endif |
122 | 610k | if (bClear) |
123 | 602k | { |
124 | 602k | std::memset(pDIB->mpBits, 0, size); |
125 | 602k | } |
126 | 610k | } |
127 | 610k | catch (const std::bad_alloc&) |
128 | 610k | { |
129 | 0 | pDIB.reset(); |
130 | 0 | } |
131 | | |
132 | 610k | return pDIB; |
133 | 610k | } |
134 | | |
135 | | void SvpSalBitmap::Create(const std::optional<BitmapBuffer>& pBuf) |
136 | 10.3k | { |
137 | 10.3k | Destroy(); |
138 | 10.3k | moDIB = pBuf; |
139 | 10.3k | } |
140 | | |
141 | | bool SvpSalBitmap::ImplCreate(const Size& rSize, vcl::PixelFormat ePixelFormat, |
142 | | const BitmapPalette& rPal, bool bClear, bool bWithoutAlpha) |
143 | 610k | { |
144 | 610k | Destroy(); |
145 | 610k | moDIB = ImplCreateDIB(rSize, ePixelFormat, rPal, bClear, bWithoutAlpha); |
146 | 610k | return moDIB.has_value(); |
147 | 610k | } |
148 | | |
149 | | bool SvpSalBitmap::Create(const Size& rSize, vcl::PixelFormat ePixelFormat, const BitmapPalette& rPal) |
150 | 603k | { |
151 | 603k | return ImplCreate(rSize, ePixelFormat, rPal, true); |
152 | 603k | } |
153 | | |
154 | | bool SvpSalBitmap::Create(const SalBitmap& rBmp) |
155 | 94.6k | { |
156 | 94.6k | Destroy(); |
157 | | |
158 | 94.6k | const SvpSalBitmap& rSalBmp = static_cast<const SvpSalBitmap&>(rBmp); |
159 | | |
160 | 94.6k | if (rSalBmp.moDIB) |
161 | 94.5k | { |
162 | | // TODO: reference counting... |
163 | 94.5k | moDIB.emplace( *rSalBmp.moDIB ); |
164 | | |
165 | 94.5k | const size_t size = moDIB->mnScanlineSize * moDIB->mnHeight; |
166 | 94.5k | if (size > SAL_MAX_INT32/2) |
167 | 0 | { |
168 | 0 | moDIB.reset(); |
169 | 0 | return false; |
170 | 0 | } |
171 | | |
172 | | // TODO: get rid of this when BitmapBuffer gets copy constructor |
173 | 94.5k | try |
174 | 94.5k | { |
175 | 94.5k | moDIB->mpBits = new sal_uInt8[size]; |
176 | 94.5k | std::memcpy(moDIB->mpBits, rSalBmp.moDIB->mpBits, size); |
177 | 94.5k | } |
178 | 94.5k | catch (const std::bad_alloc&) |
179 | 94.5k | { |
180 | 0 | moDIB.reset(); |
181 | 0 | } |
182 | 94.5k | } |
183 | | |
184 | 94.6k | return !rSalBmp.moDIB.has_value() || moDIB.has_value(); |
185 | 94.6k | } |
186 | | |
187 | | bool SvpSalBitmap::Create( const SalBitmap& /*rSalBmp*/, |
188 | | SalGraphics& /*rGraphics*/ ) |
189 | 0 | { |
190 | 0 | return false; |
191 | 0 | } |
192 | | |
193 | | bool SvpSalBitmap::Create( const css::uno::Reference< css::rendering::XBitmapCanvas >& /*xBitmapCanvas*/, Size& /*rSize*/ ) |
194 | 0 | { |
195 | 0 | return false; |
196 | 0 | } |
197 | | |
198 | | void SvpSalBitmap::Destroy() |
199 | 1.43M | { |
200 | 1.43M | if (moDIB.has_value()) |
201 | 714k | { |
202 | 714k | delete[] moDIB->mpBits; |
203 | 714k | moDIB.reset(); |
204 | 714k | } |
205 | 1.43M | } |
206 | | |
207 | | Size SvpSalBitmap::GetSize() const |
208 | 1.01M | { |
209 | 1.01M | Size aSize; |
210 | | |
211 | 1.01M | if (moDIB.has_value()) |
212 | 1.01M | { |
213 | 1.01M | aSize.setWidth( moDIB->mnWidth ); |
214 | 1.01M | aSize.setHeight( moDIB->mnHeight ); |
215 | 1.01M | } |
216 | | |
217 | 1.01M | return aSize; |
218 | 1.01M | } |
219 | | |
220 | | ScanlineFormat SvpSalBitmap::GetScanlineFormat() const |
221 | 474k | { |
222 | 474k | if (!moDIB.has_value()) |
223 | 1 | return ScanlineFormat::NONE; |
224 | 474k | return moDIB->meFormat; |
225 | 474k | } |
226 | | |
227 | | BitmapBuffer* SvpSalBitmap::AcquireBuffer(BitmapAccessMode) |
228 | 914k | { |
229 | 914k | return moDIB ? &*moDIB : nullptr; |
230 | 914k | } |
231 | | |
232 | | void SvpSalBitmap::ReleaseBuffer(BitmapBuffer*, BitmapAccessMode nMode) |
233 | 913k | { |
234 | 913k | if( nMode == BitmapAccessMode::Write ) |
235 | 704k | InvalidateChecksum(); |
236 | 913k | } |
237 | | |
238 | | bool SvpSalBitmap::GetSystemData( BitmapSystemData& ) |
239 | 0 | { |
240 | 0 | return false; |
241 | 0 | } |
242 | | |
243 | | bool SvpSalBitmap::ScalingSupported() const |
244 | 8.28k | { |
245 | 8.28k | return false; |
246 | 8.28k | } |
247 | | |
248 | | bool SvpSalBitmap::Scale( const double& /*rScaleX*/, const double& /*rScaleY*/, BmpScaleFlag /*nScaleFlag*/ ) |
249 | 0 | { |
250 | 0 | return false; |
251 | 0 | } |
252 | | |
253 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |