LibreOffice Module vcl (master) 1
BitmapWriteAccess.cxx
Go to the documentation of this file.
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#include <tools/debug.hxx>
23
25#include <bitmap/bmpfast.hxx>
26
29{
30}
31
33
35{
36 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
37 SAL_WARN_IF(nY >= rReadAcc.Height(), "vcl", "y-coordinate in source out of range!");
38 SAL_WARN_IF((!HasPalette() || !rReadAcc.HasPalette())
39 && (HasPalette() || rReadAcc.HasPalette()),
40 "vcl", "No copying possible between palette bitmap and TC bitmap!");
41
42 if ((GetScanlineFormat() == rReadAcc.GetScanlineFormat())
43 && (GetScanlineSize() >= rReadAcc.GetScanlineSize()))
44 {
45 memcpy(GetScanline(nY), rReadAcc.GetScanline(nY), rReadAcc.GetScanlineSize());
46 }
47 else
48 {
49 tools::Long nWidth = std::min(mpBuffer->mnWidth, rReadAcc.Width());
51 {
52 Scanline pScanline = GetScanline(nY);
53 Scanline pScanlineRead = rReadAcc.GetScanline(nY);
54 for (tools::Long nX = 0; nX < nWidth; nX++)
55 SetPixelOnData(pScanline, nX, rReadAcc.GetPixelFromData(pScanlineRead, nX));
56 }
57 }
58}
59
61 ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
62{
63 const ScanlineFormat nFormat = RemoveScanline(nSrcScanlineFormat);
64
65 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
67 || (!HasPalette() && nFormat > ScanlineFormat::N8BitPal),
68 "No copying possible between palette and non palette scanlines!");
69
70 const sal_uInt32 nCount = std::min(GetScanlineSize(), nSrcScanlineSize);
71
72 if (!nCount)
73 return;
74
75 if (GetScanlineFormat() == RemoveScanline(nSrcScanlineFormat))
76 memcpy(GetScanline(nY), aSrcScanline, nCount);
77 else
78 {
79 if (ImplFastCopyScanline(nY, *ImplGetBitmapBuffer(), aSrcScanline, nSrcScanlineFormat,
80 nSrcScanlineSize))
81 return;
82
84 "No support for pixel formats with color masks yet!");
85 FncGetPixel pFncGetPixel;
86 switch (nFormat)
87 {
89 pFncGetPixel = GetPixelForN1BitMsbPal;
90 break;
92 pFncGetPixel = GetPixelForN8BitPal;
93 break;
95 pFncGetPixel = GetPixelForN24BitTcBgr;
96 break;
98 pFncGetPixel = GetPixelForN24BitTcRgb;
99 break;
102 pFncGetPixel = GetPixelForN32BitTcAbgr;
103 else
104 pFncGetPixel = GetPixelForN32BitTcXbgr;
105 break;
108 pFncGetPixel = GetPixelForN32BitTcArgb;
109 else
110 pFncGetPixel = GetPixelForN32BitTcXrgb;
111 break;
114 pFncGetPixel = GetPixelForN32BitTcBgra;
115 else
116 pFncGetPixel = GetPixelForN32BitTcBgrx;
117 break;
120 pFncGetPixel = GetPixelForN32BitTcRgba;
121 else
122 pFncGetPixel = GetPixelForN32BitTcRgbx;
123 break;
125 pFncGetPixel = GetPixelForN32BitTcMask;
126 break;
127
128 default:
129 assert(false);
130 pFncGetPixel = nullptr;
131 break;
132 }
133
134 if (pFncGetPixel)
135 {
136 const ColorMask aDummyMask;
137 Scanline pScanline = GetScanline(nY);
138 for (tools::Long nX = 0, nWidth = mpBuffer->mnWidth; nX < nWidth; ++nX)
139 SetPixelOnData(pScanline, nX, pFncGetPixel(aSrcScanline, nX, aDummyMask));
140 }
141 }
142}
143
145{
146 if (rColor.GetAlpha() == 0)
147 {
148 mpLineColor.reset();
149 }
150 else
151 {
152 if (HasPalette())
153 {
154 mpLineColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
155 }
156 else
157 {
158 mpLineColor = BitmapColor(rColor);
159 }
160 }
161}
162
164
166{
167 if (rColor.GetAlpha() == 0)
168 {
169 mpFillColor.reset();
170 }
171 else
172 {
173 if (HasPalette())
174 {
175 mpFillColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
176 }
177 else
178 {
179 mpFillColor = BitmapColor(rColor);
180 }
181 }
182}
183
185{
186 // convert the color format from RGB to palette index if needed
187 // TODO: provide and use Erase( BitmapColor& method)
188 BitmapColor aColor = rColor;
189 if (HasPalette())
190 {
191 aColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
192 }
193
194 // try fast bitmap method first
195 if (ImplFastEraseBitmap(*mpBuffer, aColor))
196 return;
197
199 if (aRect.IsEmpty())
200 return;
201 // clear the bitmap by filling the first line pixel by pixel,
202 // then dup the first line over each other line
203 Scanline pFirstScanline = GetScanline(0);
204 const tools::Long nEndX = aRect.Right();
205 for (tools::Long nX = 0; nX <= nEndX; ++nX)
206 SetPixelOnData(pFirstScanline, nX, rColor);
207 const auto nScanlineSize = GetScanlineSize();
208 const tools::Long nEndY = aRect.Bottom();
209 for (tools::Long nY = 1; nY <= nEndY; nY++)
210 {
211 Scanline pDestScanline = GetScanline(nY);
212 memcpy(pDestScanline, pFirstScanline, nScanlineSize);
213 }
214}
215
216void BitmapWriteAccess::DrawLine(const Point& rStart, const Point& rEnd)
217{
218 if (!mpLineColor)
219 return;
220
221 const BitmapColor& rLineColor = *mpLineColor;
222 tools::Long nX, nY;
223
224 if (rStart.X() == rEnd.X())
225 {
226 // Vertical Line
227 const tools::Long nEndY = rEnd.Y();
228
229 nX = rStart.X();
230 nY = rStart.Y();
231
232 if (nEndY > nY)
233 {
234 for (; nY <= nEndY; nY++)
235 SetPixel(nY, nX, rLineColor);
236 }
237 else
238 {
239 for (; nY >= nEndY; nY--)
240 SetPixel(nY, nX, rLineColor);
241 }
242 }
243 else if (rStart.Y() == rEnd.Y())
244 {
245 // Horizontal Line
246 const tools::Long nEndX = rEnd.X();
247
248 nX = rStart.X();
249 nY = rStart.Y();
250
251 if (nEndX > nX)
252 {
253 for (; nX <= nEndX; nX++)
254 SetPixel(nY, nX, rLineColor);
255 }
256 else
257 {
258 for (; nX >= nEndX; nX--)
259 SetPixel(nY, nX, rLineColor);
260 }
261 }
262 else
263 {
264 const tools::Long nDX = std::abs(rEnd.X() - rStart.X());
265 const tools::Long nDY = std::abs(rEnd.Y() - rStart.Y());
266 tools::Long nX1;
267 tools::Long nY1;
268 tools::Long nX2;
269 tools::Long nY2;
270
271 if (nDX >= nDY)
272 {
273 if (rStart.X() < rEnd.X())
274 {
275 nX1 = rStart.X();
276 nY1 = rStart.Y();
277 nX2 = rEnd.X();
278 nY2 = rEnd.Y();
279 }
280 else
281 {
282 nX1 = rEnd.X();
283 nY1 = rEnd.Y();
284 nX2 = rStart.X();
285 nY2 = rStart.Y();
286 }
287
288 const tools::Long nDYX = (nDY - nDX) << 1;
289 const tools::Long nDY2 = nDY << 1;
290 tools::Long nD = nDY2 - nDX;
291 bool bPos = nY1 < nY2;
292
293 for (nX = nX1, nY = nY1; nX <= nX2; nX++)
294 {
295 SetPixel(nY, nX, rLineColor);
296
297 if (nD < 0)
298 nD += nDY2;
299 else
300 {
301 nD += nDYX;
302
303 if (bPos)
304 nY++;
305 else
306 nY--;
307 }
308 }
309 }
310 else
311 {
312 if (rStart.Y() < rEnd.Y())
313 {
314 nX1 = rStart.X();
315 nY1 = rStart.Y();
316 nX2 = rEnd.X();
317 nY2 = rEnd.Y();
318 }
319 else
320 {
321 nX1 = rEnd.X();
322 nY1 = rEnd.Y();
323 nX2 = rStart.X();
324 nY2 = rStart.Y();
325 }
326
327 const tools::Long nDYX = (nDX - nDY) << 1;
328 const tools::Long nDY2 = nDX << 1;
329 tools::Long nD = nDY2 - nDY;
330 bool bPos = nX1 < nX2;
331
332 for (nX = nX1, nY = nY1; nY <= nY2; nY++)
333 {
334 SetPixel(nY, nX, rLineColor);
335
336 if (nD < 0)
337 nD += nDY2;
338 else
339 {
340 nD += nDYX;
341
342 if (bPos)
343 nX++;
344 else
345 nX--;
346 }
347 }
348 }
349 }
350}
351
353{
354 if (!mpFillColor)
355 return;
356
357 const BitmapColor& rFillColor = *mpFillColor;
359
360 aRect.Intersection(rRect);
361
362 if (aRect.IsEmpty())
363 return;
364
365 const tools::Long nStartX = rRect.Left();
366 const tools::Long nStartY = rRect.Top();
367 const tools::Long nEndX = rRect.Right();
368 const tools::Long nEndY = rRect.Bottom();
369
370 for (tools::Long nY = nStartY; nY <= nEndY; nY++)
371 {
372 Scanline pScanline = GetScanline(nY);
373 for (tools::Long nX = nStartX; nX <= nEndX; nX++)
374 {
375 SetPixelOnData(pScanline, nX, rFillColor);
376 }
377 }
378}
379
381{
382 if (mpFillColor)
383 FillRect(rRect);
384
386 {
387 DrawLine(rRect.TopLeft(), rRect.TopRight());
388 DrawLine(rRect.TopRight(), rRect.BottomRight());
389 DrawLine(rRect.BottomRight(), rRect.BottomLeft());
390 DrawLine(rRect.BottomLeft(), rRect.TopLeft());
391 }
392}
393
394/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
BitmapAccessMode
BitmapColor(* FncGetPixel)(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
bool Bitmap32IsPreMultipled()
const sal_uInt8 * ConstScanline
Definition: Scanline.hxx:27
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
ScanlineFormat
Definition: Scanline.hxx:29
ScanlineFormat RemoveScanline(ScanlineFormat nFormat)
Definition: Scanline.hxx:53
bool ImplFastEraseBitmap(BitmapBuffer &rDst, const BitmapColor &rColor)
Definition: bmpfast.cxx:763
bool ImplFastCopyScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
Definition: bmpfast.cxx:506
tools::Long Height() const
tools::Long Width() const
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rBitmapColor) const
bool HasPalette() const
ScanlineFormat GetScanlineFormat() const
BitmapBuffer * mpBuffer
sal_uInt32 GetScanlineSize() const
BitmapBuffer * ImplGetBitmapBuffer() const
static BitmapColor GetPixelForN8BitPal(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcRgbx(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN24BitTcRgb(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcXbgr(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcBgra(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN1BitMsbPal(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN24BitTcBgr(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcAbgr(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
void SetPixelOnData(sal_uInt8 *pData, tools::Long nX, const BitmapColor &rBitmapColor)
static BitmapColor GetPixelForN32BitTcBgrx(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcArgb(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
static BitmapColor GetPixelForN32BitTcXrgb(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
Scanline GetScanline(tools::Long nY) const
static BitmapColor GetPixelForN32BitTcRgba(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcMask(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
std::optional< BitmapColor > mpLineColor
virtual ~BitmapWriteAccess() override
void SetLineColor(const Color &rColor)
void CopyScanline(tools::Long nY, const BitmapReadAccess &rReadAcc)
void DrawLine(const Point &rStart, const Point &rEnd)
BitmapWriteAccess()=delete
void SetPixel(tools::Long nY, tools::Long nX, const BitmapColor &rBitmapColor)
void FillRect(const tools::Rectangle &rRect)
std::optional< BitmapColor > mpFillColor
void DrawRect(const tools::Rectangle &rRect)
void Erase(const Color &rColor)
Size GetSizePixel() const
sal_uInt8 GetAlpha() const
constexpr tools::Long Y() const
constexpr tools::Long X() const
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr tools::Long Right() const
constexpr Point BottomRight() const
constexpr Point TopRight() const
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
constexpr bool IsEmpty() const
constexpr Point BottomLeft() const
int nCount
#define DBG_ASSERT(sCon, aError)
#define SAL_WARN_IF(condition, area, stream)
long Long
double mnHeight
tools::Long mnWidth
unsigned char sal_uInt8