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