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 = GetPixelForN1BitLsbPal;
93  break;
95  pFncGetPixel = GetPixelForN8BitPal;
96  break;
98  pFncGetPixel = GetPixelForN24BitTcBgr;
99  break;
101  pFncGetPixel = GetPixelForN24BitTcRgb;
102  break;
105  pFncGetPixel = GetPixelForN32BitTcAbgr;
106  else
107  pFncGetPixel = GetPixelForN32BitTcXbgr;
108  break;
111  pFncGetPixel = GetPixelForN32BitTcArgb;
112  else
113  pFncGetPixel = GetPixelForN32BitTcXrgb;
114  break;
117  pFncGetPixel = GetPixelForN32BitTcBgra;
118  else
119  pFncGetPixel = GetPixelForN32BitTcBgrx;
120  break;
123  pFncGetPixel = GetPixelForN32BitTcRgba;
124  else
125  pFncGetPixel = GetPixelForN32BitTcRgbx;
126  break;
128  pFncGetPixel = GetPixelForN32BitTcMask;
129  break;
130 
131  default:
132  assert(false);
133  pFncGetPixel = nullptr;
134  break;
135  }
136 
137  if (pFncGetPixel)
138  {
139  const ColorMask aDummyMask;
140  Scanline pScanline = GetScanline(nY);
141  for (tools::Long nX = 0, nWidth = mpBuffer->mnWidth; nX < nWidth; ++nX)
142  SetPixelOnData(pScanline, nX, pFncGetPixel(aSrcScanline, nX, aDummyMask));
143  }
144  }
145 }
146 
148 {
149  if (rColor.GetAlpha() == 0)
150  {
151  mpLineColor.reset();
152  }
153  else
154  {
155  if (HasPalette())
156  {
157  mpLineColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
158  }
159  else
160  {
161  mpLineColor = BitmapColor(rColor);
162  }
163  }
164 }
165 
167 
169 {
170  if (rColor.GetAlpha() == 0)
171  {
172  mpFillColor.reset();
173  }
174  else
175  {
176  if (HasPalette())
177  {
178  mpFillColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
179  }
180  else
181  {
182  mpFillColor = BitmapColor(rColor);
183  }
184  }
185 }
186 
187 void BitmapWriteAccess::Erase(const Color& rColor)
188 {
189  // convert the color format from RGB to palette index if needed
190  // TODO: provide and use Erase( BitmapColor& method)
191  BitmapColor aColor = rColor;
192  if (HasPalette())
193  {
194  aColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
195  }
196 
197  // try fast bitmap method first
198  if (ImplFastEraseBitmap(*mpBuffer, aColor))
199  return;
200 
202  if (aRect.IsEmpty())
203  return;
204  // clear the bitmap by filling the first line pixel by pixel,
205  // then dup the first line over each other line
206  Scanline pFirstScanline = GetScanline(0);
207  const tools::Long nEndX = aRect.Right();
208  for (tools::Long nX = 0; nX <= nEndX; ++nX)
209  SetPixelOnData(pFirstScanline, nX, rColor);
210  const auto nScanlineSize = GetScanlineSize();
211  const tools::Long nEndY = aRect.Bottom();
212  for (tools::Long nY = 1; nY <= nEndY; nY++)
213  {
214  Scanline pDestScanline = GetScanline(nY);
215  memcpy(pDestScanline, pFirstScanline, nScanlineSize);
216  }
217 }
218 
219 void BitmapWriteAccess::DrawLine(const Point& rStart, const Point& rEnd)
220 {
221  if (!mpLineColor)
222  return;
223 
224  const BitmapColor& rLineColor = *mpLineColor;
225  tools::Long nX, nY;
226 
227  if (rStart.X() == rEnd.X())
228  {
229  // Vertical Line
230  const tools::Long nEndY = rEnd.Y();
231 
232  nX = rStart.X();
233  nY = rStart.Y();
234 
235  if (nEndY > nY)
236  {
237  for (; nY <= nEndY; nY++)
238  SetPixel(nY, nX, rLineColor);
239  }
240  else
241  {
242  for (; nY >= nEndY; nY--)
243  SetPixel(nY, nX, rLineColor);
244  }
245  }
246  else if (rStart.Y() == rEnd.Y())
247  {
248  // Horizontal Line
249  const tools::Long nEndX = rEnd.X();
250 
251  nX = rStart.X();
252  nY = rStart.Y();
253 
254  if (nEndX > nX)
255  {
256  for (; nX <= nEndX; nX++)
257  SetPixel(nY, nX, rLineColor);
258  }
259  else
260  {
261  for (; nX >= nEndX; nX--)
262  SetPixel(nY, nX, rLineColor);
263  }
264  }
265  else
266  {
267  const tools::Long nDX = std::abs(rEnd.X() - rStart.X());
268  const tools::Long nDY = std::abs(rEnd.Y() - rStart.Y());
269  tools::Long nX1;
270  tools::Long nY1;
271  tools::Long nX2;
272  tools::Long nY2;
273 
274  if (nDX >= nDY)
275  {
276  if (rStart.X() < rEnd.X())
277  {
278  nX1 = rStart.X();
279  nY1 = rStart.Y();
280  nX2 = rEnd.X();
281  nY2 = rEnd.Y();
282  }
283  else
284  {
285  nX1 = rEnd.X();
286  nY1 = rEnd.Y();
287  nX2 = rStart.X();
288  nY2 = rStart.Y();
289  }
290 
291  const tools::Long nDYX = (nDY - nDX) << 1;
292  const tools::Long nDY2 = nDY << 1;
293  tools::Long nD = nDY2 - nDX;
294  bool bPos = nY1 < nY2;
295 
296  for (nX = nX1, nY = nY1; nX <= nX2; nX++)
297  {
298  SetPixel(nY, nX, rLineColor);
299 
300  if (nD < 0)
301  nD += nDY2;
302  else
303  {
304  nD += nDYX;
305 
306  if (bPos)
307  nY++;
308  else
309  nY--;
310  }
311  }
312  }
313  else
314  {
315  if (rStart.Y() < rEnd.Y())
316  {
317  nX1 = rStart.X();
318  nY1 = rStart.Y();
319  nX2 = rEnd.X();
320  nY2 = rEnd.Y();
321  }
322  else
323  {
324  nX1 = rEnd.X();
325  nY1 = rEnd.Y();
326  nX2 = rStart.X();
327  nY2 = rStart.Y();
328  }
329 
330  const tools::Long nDYX = (nDX - nDY) << 1;
331  const tools::Long nDY2 = nDX << 1;
332  tools::Long nD = nDY2 - nDY;
333  bool bPos = nX1 < nX2;
334 
335  for (nX = nX1, nY = nY1; nY <= nY2; nY++)
336  {
337  SetPixel(nY, nX, rLineColor);
338 
339  if (nD < 0)
340  nD += nDY2;
341  else
342  {
343  nD += nDYX;
344 
345  if (bPos)
346  nX++;
347  else
348  nX--;
349  }
350  }
351  }
352  }
353 }
354 
356 {
357  if (!mpFillColor)
358  return;
359 
360  const BitmapColor& rFillColor = *mpFillColor;
362 
363  aRect.Intersection(rRect);
364 
365  if (aRect.IsEmpty())
366  return;
367 
368  const tools::Long nStartX = rRect.Left();
369  const tools::Long nStartY = rRect.Top();
370  const tools::Long nEndX = rRect.Right();
371  const tools::Long nEndY = rRect.Bottom();
372 
373  for (tools::Long nY = nStartY; nY <= nEndY; nY++)
374  {
375  Scanline pScanline = GetScanline(nY);
376  for (tools::Long nX = nStartX; nX <= nEndX; nX++)
377  {
378  SetPixelOnData(pScanline, nX, rFillColor);
379  }
380  }
381 }
382 
384 {
385  if (mpFillColor)
386  FillRect(rRect);
387 
388  if (mpLineColor && (!mpFillColor || (*mpFillColor != *mpLineColor)))
389  {
390  DrawLine(rRect.TopLeft(), rRect.TopRight());
391  DrawLine(rRect.TopRight(), rRect.BottomRight());
392  DrawLine(rRect.BottomRight(), rRect.BottomLeft());
393  DrawLine(rRect.BottomLeft(), rRect.TopLeft());
394  }
395 }
396 
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
double mnHeight
static BitmapColor GetPixelForN1BitMsbPal(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
tools::Long Height() const
sal_uInt8 GetAlpha() const
static BitmapColor GetPixelForN32BitTcRgbx(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcXbgr(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
void DrawRect(const tools::Rectangle &rRect)
constexpr tools::Long Left() const
long Long
static BitmapColor GetPixelForN32BitTcXrgb(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rBitmapColor) const
Size GetSizePixel() const
std::optional< BitmapColor > mpLineColor
void SetPixelOnData(sal_uInt8 *pData, tools::Long nX, const BitmapColor &rBitmapColor)
ScanlineFormat
Definition: Scanline.hxx:29
void FillRect(const tools::Rectangle &rRect)
Scanline GetScanline(tools::Long nY) const
constexpr Point BottomLeft() const
int nCount
void SetPixel(tools::Long nY, tools::Long nX, const BitmapColor &rBitmapColor)
BitmapBuffer * mpBuffer
SAL_DLLPRIVATE BitmapBuffer * ImplGetBitmapBuffer() const
sal_uInt8 * Scanline
Definition: Scanline.hxx:26
sal_uInt32 GetScanlineSize() const
#define DBG_ASSERT(sCon, aError)
bool HasPalette() const
ScanlineFormat GetScanlineFormat() const
static BitmapColor GetPixelForN24BitTcBgr(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
void Erase(const Color &rColor)
static BitmapColor GetPixelForN32BitTcBgrx(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcMask(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcRgba(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
BitmapAccessMode
constexpr tools::Long Right() const
tools::Long Width() const
BitmapWriteAccess()=delete
constexpr tools::Long Top() const
static BitmapColor GetPixelForN1BitLsbPal(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
bool Bitmap32IsPreMultipled()
static BitmapColor GetPixelForN32BitTcAbgr(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
constexpr Point TopLeft() const
void SetLineColor(const Color &rColor)
const sal_uInt8 * ConstScanline
Definition: Scanline.hxx:27
constexpr tools::Long Bottom() const
static BitmapColor GetPixelForN8BitPal(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
static BitmapColor GetPixelForN32BitTcBgra(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
bool ImplFastCopyScanline(tools::Long nY, BitmapBuffer &rDst, ConstScanline aSrcScanline, ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
Definition: bmpfast.cxx:508
#define SAL_WARN_IF(condition, area, stream)
void CopyScanline(tools::Long nY, const BitmapReadAccess &rReadAcc)
constexpr Point TopRight() const
static BitmapColor GetPixelForN24BitTcRgb(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
void DrawLine(const Point &rStart, const Point &rEnd)
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
std::optional< BitmapColor > mpFillColor
ScanlineFormat RemoveScanline(ScanlineFormat nFormat)
Definition: Scanline.hxx:54
constexpr Point BottomRight() const
virtual ~BitmapWriteAccess() override
BitmapColor(* FncGetPixel)(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
tools::Long mnWidth
static BitmapColor GetPixelForN32BitTcArgb(ConstScanline pScanline, tools::Long nX, const ColorMask &rMask)
bool ImplFastEraseBitmap(BitmapBuffer &rDst, const BitmapColor &rColor)
Definition: bmpfast.cxx:767