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