1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <Qt5Bitmap.hxx>
21 #include <Qt5Tools.hxx>
22 #include <Qt5Graphics.hxx>
24 #include <QtGui/QImage>
25 #include <QtCore/QVector>
26 #include <QtGui/QColor>
28 #include <o3tl/safeint.hxx>
29 #include <sal/log.hxx>
30 #include <tools/helpers.hxx>
32 Qt5Bitmap::Qt5Bitmap() {}
34 Qt5Bitmap::Qt5Bitmap(const QImage
& rImage
) { m_pImage
.reset(new QImage(rImage
)); }
36 bool Qt5Bitmap::Create(const Size
& rSize
, sal_uInt16 nBitCount
, const BitmapPalette
& rPal
)
39 (nBitCount
== 1 || nBitCount
== 4 || nBitCount
== 8 || nBitCount
== 24 || nBitCount
== 32)
40 && "Unsupported BitCount!");
43 assert(2 >= rPal
.GetEntryCount());
45 assert(16 >= rPal
.GetEntryCount());
47 assert(256 >= rPal
.GetEntryCount());
53 bool bFail
= o3tl::checked_multiply
<sal_uInt32
>(rSize
.Width(), nBitCount
, m_nScanline
);
56 SAL_WARN("vcl.gdi", "checked multiply failed");
59 m_nScanline
= AlignedWidth4Bytes(m_nScanline
);
60 sal_uInt8
* pBuffer
= nullptr;
61 if (0 != m_nScanline
&& 0 != rSize
.Height())
62 pBuffer
= new sal_uInt8
[m_nScanline
* rSize
.Height()];
63 m_pBuffer
.reset(pBuffer
);
67 m_pImage
.reset(new QImage(toQSize(rSize
), getBitFormat(nBitCount
)));
68 m_pImage
->fill(Qt::transparent
);
73 auto count
= rPal
.GetEntryCount();
74 if (nBitCount
!= 4 && count
&& m_pImage
.get())
76 QVector
<QRgb
> aColorTable(count
);
77 for (unsigned i
= 0; i
< count
; ++i
)
78 aColorTable
[i
] = qRgb(rPal
[i
].GetRed(), rPal
[i
].GetGreen(), rPal
[i
].GetBlue());
79 m_pImage
->setColorTable(aColorTable
);
84 bool Qt5Bitmap::Create(const SalBitmap
& rSalBmp
)
86 const Qt5Bitmap
* pBitmap
= static_cast<const Qt5Bitmap
*>(&rSalBmp
);
87 if (pBitmap
->m_pImage
.get())
89 m_pImage
.reset(new QImage(*pBitmap
->m_pImage
));
94 m_aSize
= pBitmap
->m_aSize
;
95 m_nScanline
= pBitmap
->m_nScanline
;
96 sal_uInt8
* pBuffer
= nullptr;
97 if (0 != m_nScanline
&& 0 != m_aSize
.Height())
99 sal_uInt32 nSize
= m_nScanline
* m_aSize
.Height();
100 pBuffer
= new sal_uInt8
[nSize
];
101 memcpy(pBuffer
, pBitmap
->m_pBuffer
.get(), nSize
);
103 m_pBuffer
.reset(pBuffer
);
106 m_aPalette
= pBitmap
->m_aPalette
;
110 bool Qt5Bitmap::Create(const SalBitmap
& rSalBmp
, SalGraphics
* pSalGraphics
)
112 const Qt5Bitmap
* pBitmap
= static_cast<const Qt5Bitmap
*>(&rSalBmp
);
113 Qt5Graphics
* pGraphics
= static_cast<Qt5Graphics
*>(pSalGraphics
);
114 QImage
* pImage
= pGraphics
->m_pQImage
;
115 m_pImage
.reset(new QImage(pBitmap
->m_pImage
->convertToFormat(pImage
->format())));
120 bool Qt5Bitmap::Create(const SalBitmap
& rSalBmp
, sal_uInt16 nNewBitCount
)
122 assert((nNewBitCount
== 1 || nNewBitCount
== 4 || nNewBitCount
== 8 || nNewBitCount
== 24
123 || nNewBitCount
== 32)
124 && "Unsupported BitCount!");
126 const Qt5Bitmap
* pBitmap
= static_cast<const Qt5Bitmap
*>(&rSalBmp
);
127 if (pBitmap
->m_pBuffer
.get())
129 if (nNewBitCount
!= 32)
132 // convert 4bit indexed palette to 32bit ARGB
133 m_pImage
.reset(new QImage(pBitmap
->m_aSize
.Width(), pBitmap
->m_aSize
.Height(),
134 getBitFormat(nNewBitCount
)));
135 m_pImage
->fill(Qt::transparent
);
137 // prepare a whole palette
138 const BitmapPalette
& rPal
= pBitmap
->m_aPalette
;
139 QVector
<QRgb
> colorTable(16);
140 int i
= 0, maxEntry
= pBitmap
->m_aPalette
.GetEntryCount();
141 assert(maxEntry
<= 16 && maxEntry
>= 0);
142 for (; i
< maxEntry
; ++i
)
143 colorTable
[i
] = qRgb(rPal
[i
].GetRed(), rPal
[i
].GetGreen(), rPal
[i
].GetBlue());
145 colorTable
[i
] = qRgb(0, 0, 0);
147 sal_uInt32
* image_data
= reinterpret_cast<sal_uInt32
*>(m_pImage
->bits());
148 sal_uInt8
* buffer_data_pos
= pBitmap
->m_pBuffer
.get();
149 sal_uInt32 nWidth
= pBitmap
->m_aSize
.Height() / 2;
150 bool isOdd(0 != pBitmap
->m_aSize
.Height() % 2);
152 for (long h
= 0; h
< pBitmap
->m_aSize
.Height(); ++h
)
154 sal_uInt8
* buffer_data
= buffer_data_pos
;
155 buffer_data_pos
+= pBitmap
->m_nScanline
;
156 for (sal_uInt32 w
= 0; w
< nWidth
; ++w
)
158 *image_data
= static_cast<sal_uInt32
>(colorTable
.at(*buffer_data
>> 4));
160 *image_data
= static_cast<sal_uInt32
>(colorTable
.at(*buffer_data
& 0xF));
166 *image_data
= static_cast<sal_uInt32
>(colorTable
.at(*buffer_data
>> 4));
172 m_pImage
.reset(new QImage(pBitmap
->m_pImage
->convertToFormat(getBitFormat(nNewBitCount
))));
177 bool Qt5Bitmap::Create(const css::uno::Reference
<css::rendering::XBitmapCanvas
>& /*rBitmapCanvas*/,
178 Size
& /*rSize*/, bool /*bMask*/)
183 void Qt5Bitmap::Destroy()
189 Size
Qt5Bitmap::GetSize() const
193 else if (m_pImage
.get())
194 return toSize(m_pImage
->size());
198 sal_uInt16
Qt5Bitmap::GetBitCount() const
202 else if (m_pImage
.get())
203 return getFormatBits(m_pImage
->format());
207 BitmapBuffer
* Qt5Bitmap::AcquireBuffer(BitmapAccessMode
/*nMode*/)
209 static const BitmapPalette aEmptyPalette
;
211 if (!(m_pImage
.get() || m_pBuffer
.get()))
214 BitmapBuffer
* pBuffer
= new BitmapBuffer
;
218 pBuffer
->mnWidth
= m_aSize
.Width();
219 pBuffer
->mnHeight
= m_aSize
.Height();
220 pBuffer
->mnBitCount
= 4;
221 pBuffer
->mpBits
= m_pBuffer
.get();
222 pBuffer
->mnScanlineSize
= m_nScanline
;
226 pBuffer
->mnWidth
= m_pImage
->width();
227 pBuffer
->mnHeight
= m_pImage
->height();
228 pBuffer
->mnBitCount
= getFormatBits(m_pImage
->format());
229 pBuffer
->mpBits
= m_pImage
->bits();
230 pBuffer
->mnScanlineSize
= m_pImage
->bytesPerLine();
233 switch (pBuffer
->mnBitCount
)
236 pBuffer
->mnFormat
= ScanlineFormat::N1BitMsbPal
| ScanlineFormat::TopDown
;
237 pBuffer
->maPalette
= m_aPalette
;
240 pBuffer
->mnFormat
= ScanlineFormat::N4BitMsnPal
| ScanlineFormat::TopDown
;
241 pBuffer
->maPalette
= m_aPalette
;
244 pBuffer
->mnFormat
= ScanlineFormat::N8BitPal
| ScanlineFormat::TopDown
;
245 pBuffer
->maPalette
= m_aPalette
;
248 pBuffer
->mnFormat
= ScanlineFormat::N24BitTcRgb
| ScanlineFormat::TopDown
;
249 pBuffer
->maPalette
= aEmptyPalette
;
254 pBuffer
->mnFormat
= ScanlineFormat::N32BitTcArgb
| ScanlineFormat::TopDown
;
256 pBuffer
->mnFormat
= ScanlineFormat::N32BitTcBgra
| ScanlineFormat::TopDown
;
258 pBuffer
->maPalette
= aEmptyPalette
;
268 void Qt5Bitmap::ReleaseBuffer(BitmapBuffer
* pBuffer
, BitmapAccessMode nMode
)
270 m_aPalette
= pBuffer
->maPalette
;
271 auto count
= m_aPalette
.GetEntryCount();
272 if (pBuffer
->mnBitCount
!= 4 && count
)
274 QVector
<QRgb
> aColorTable(count
);
275 for (unsigned i
= 0; i
< count
; ++i
)
277 = qRgb(m_aPalette
[i
].GetRed(), m_aPalette
[i
].GetGreen(), m_aPalette
[i
].GetBlue());
278 m_pImage
->setColorTable(aColorTable
);
281 if (nMode
== BitmapAccessMode::Write
)
282 InvalidateChecksum();
285 bool Qt5Bitmap::GetSystemData(BitmapSystemData
& /*rData*/) { return false; }
287 bool Qt5Bitmap::ScalingSupported() const { return false; }
289 bool Qt5Bitmap::Scale(const double& /*rScaleX*/, const double& /*rScaleY*/,
290 BmpScaleFlag
/*nScaleFlag*/)
295 bool Qt5Bitmap::Replace(const Color
& /*rSearchColor*/, const Color
& /*rReplaceColor*/,
301 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */