LibreOffice Module vcl (master)  1
bmpacc3.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 
22 #include <cstdlib>
23 
24 #include <vcl/bitmap.hxx>
25 
26 #include <bmpfast.hxx>
27 #include <bitmapwriteaccess.hxx>
28 
30 {
31  if (rColor.GetTransparency() == 255)
32  {
33  mpLineColor.reset();
34  }
35  else
36  {
37  if (HasPalette())
38  {
39  mpLineColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
40  }
41  else
42  {
43  mpLineColor = BitmapColor(rColor);
44  }
45  }
46 }
47 
49 
51 {
52  if (rColor.GetTransparency() == 255)
53  {
54  mpFillColor.reset();
55  }
56  else
57  {
58  if (HasPalette())
59  {
60  mpFillColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
61  }
62  else
63  {
64  mpFillColor = BitmapColor(rColor);
65  }
66  }
67 }
68 
69 void BitmapWriteAccess::Erase(const Color& rColor)
70 {
71  // convert the color format from RGB to palette index if needed
72  // TODO: provide and use Erase( BitmapColor& method)
73  BitmapColor aColor = rColor;
74  if (HasPalette())
75  {
76  aColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
77  }
78 
79  // try fast bitmap method first
80  if (ImplFastEraseBitmap(*mpBuffer, aColor))
81  return;
82 
84  if (aRect.IsEmpty())
85  return;
86  // clear the bitmap by filling the first line pixel by pixel,
87  // then dup the first line over each other line
88  Scanline pFirstScanline = GetScanline(0);
89  const tools::Long nEndX = aRect.Right();
90  for (tools::Long nX = 0; nX <= nEndX; ++nX)
91  SetPixelOnData(pFirstScanline, nX, rColor);
92  const auto nScanlineSize = GetScanlineSize();
93  const tools::Long nEndY = aRect.Bottom();
94  for (tools::Long nY = 1; nY <= nEndY; nY++)
95  {
96  Scanline pDestScanline = GetScanline(nY);
97  memcpy(pDestScanline, pFirstScanline, nScanlineSize);
98  }
99 }
100 
101 void BitmapWriteAccess::DrawLine(const Point& rStart, const Point& rEnd)
102 {
103  if (!mpLineColor)
104  return;
105 
106  const BitmapColor& rLineColor = *mpLineColor;
107  tools::Long nX, nY;
108 
109  if (rStart.X() == rEnd.X())
110  {
111  // Vertical Line
112  const tools::Long nEndY = rEnd.Y();
113 
114  nX = rStart.X();
115  nY = rStart.Y();
116 
117  if (nEndY > nY)
118  {
119  for (; nY <= nEndY; nY++)
120  SetPixel(nY, nX, rLineColor);
121  }
122  else
123  {
124  for (; nY >= nEndY; nY--)
125  SetPixel(nY, nX, rLineColor);
126  }
127  }
128  else if (rStart.Y() == rEnd.Y())
129  {
130  // Horizontal Line
131  const tools::Long nEndX = rEnd.X();
132 
133  nX = rStart.X();
134  nY = rStart.Y();
135 
136  if (nEndX > nX)
137  {
138  for (; nX <= nEndX; nX++)
139  SetPixel(nY, nX, rLineColor);
140  }
141  else
142  {
143  for (; nX >= nEndX; nX--)
144  SetPixel(nY, nX, rLineColor);
145  }
146  }
147  else
148  {
149  const tools::Long nDX = std::abs(rEnd.X() - rStart.X());
150  const tools::Long nDY = std::abs(rEnd.Y() - rStart.Y());
151  tools::Long nX1;
152  tools::Long nY1;
153  tools::Long nX2;
154  tools::Long nY2;
155 
156  if (nDX >= nDY)
157  {
158  if (rStart.X() < rEnd.X())
159  {
160  nX1 = rStart.X();
161  nY1 = rStart.Y();
162  nX2 = rEnd.X();
163  nY2 = rEnd.Y();
164  }
165  else
166  {
167  nX1 = rEnd.X();
168  nY1 = rEnd.Y();
169  nX2 = rStart.X();
170  nY2 = rStart.Y();
171  }
172 
173  const tools::Long nDYX = (nDY - nDX) << 1;
174  const tools::Long nDY2 = nDY << 1;
175  tools::Long nD = nDY2 - nDX;
176  bool bPos = nY1 < nY2;
177 
178  for (nX = nX1, nY = nY1; nX <= nX2; nX++)
179  {
180  SetPixel(nY, nX, rLineColor);
181 
182  if (nD < 0)
183  nD += nDY2;
184  else
185  {
186  nD += nDYX;
187 
188  if (bPos)
189  nY++;
190  else
191  nY--;
192  }
193  }
194  }
195  else
196  {
197  if (rStart.Y() < rEnd.Y())
198  {
199  nX1 = rStart.X();
200  nY1 = rStart.Y();
201  nX2 = rEnd.X();
202  nY2 = rEnd.Y();
203  }
204  else
205  {
206  nX1 = rEnd.X();
207  nY1 = rEnd.Y();
208  nX2 = rStart.X();
209  nY2 = rStart.Y();
210  }
211 
212  const tools::Long nDYX = (nDX - nDY) << 1;
213  const tools::Long nDY2 = nDX << 1;
214  tools::Long nD = nDY2 - nDY;
215  bool bPos = nX1 < nX2;
216 
217  for (nX = nX1, nY = nY1; nY <= nY2; nY++)
218  {
219  SetPixel(nY, nX, rLineColor);
220 
221  if (nD < 0)
222  nD += nDY2;
223  else
224  {
225  nD += nDYX;
226 
227  if (bPos)
228  nX++;
229  else
230  nX--;
231  }
232  }
233  }
234  }
235 }
236 
238 {
239  if (!mpFillColor)
240  return;
241 
242  const BitmapColor& rFillColor = *mpFillColor;
244 
245  aRect.Intersection(rRect);
246 
247  if (aRect.IsEmpty())
248  return;
249 
250  const tools::Long nStartX = rRect.Left();
251  const tools::Long nStartY = rRect.Top();
252  const tools::Long nEndX = rRect.Right();
253  const tools::Long nEndY = rRect.Bottom();
254 
255  for (tools::Long nY = nStartY; nY <= nEndY; nY++)
256  {
257  Scanline pScanline = GetScanline(nY);
258  for (tools::Long nX = nStartX; nX <= nEndX; nX++)
259  {
260  SetPixelOnData(pScanline, nX, rFillColor);
261  }
262  }
263 }
264 
266 {
267  if (mpFillColor)
268  FillRect(rRect);
269 
270  if (mpLineColor && (!mpFillColor || (*mpFillColor != *mpLineColor)))
271  {
272  DrawLine(rRect.TopLeft(), rRect.TopRight());
273  DrawLine(rRect.TopRight(), rRect.BottomRight());
274  DrawLine(rRect.BottomRight(), rRect.BottomLeft());
275  DrawLine(rRect.BottomLeft(), rRect.TopLeft());
276  }
277 }
278 
279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Point TopLeft() const
tools::Rectangle & Intersection(const tools::Rectangle &rRect)
void DrawRect(const tools::Rectangle &rRect)
Definition: bmpacc3.cxx:265
Point BottomLeft() const
sal_uInt8 GetTransparency() const
long Long
sal_uInt16 GetBestPaletteIndex(const BitmapColor &rBitmapColor) const
Definition: bmpacc.cxx:80
Size GetSizePixel() const
std::optional< BitmapColor > mpLineColor
void SetPixelOnData(sal_uInt8 *pData, tools::Long nX, const BitmapColor &rBitmapColor)
void FillRect(const tools::Rectangle &rRect)
Definition: bmpacc3.cxx:237
tools::Long Left() const
Scanline GetScanline(tools::Long nY) const
tools::Long Bottom() const
void SetPixel(tools::Long nY, tools::Long nX, const BitmapColor &rBitmapColor)
BitmapBuffer * mpBuffer
Point BottomRight() const
sal_uInt8 * Scanline
Definition: Scanline.hxx:25
sal_uInt32 GetScanlineSize() const
bool HasPalette() const
void Erase(const Color &rColor)
Definition: bmpacc3.cxx:69
tools::Long Top() const
void SetLineColor(const Color &rColor)
Definition: bmpacc3.cxx:29
void DrawLine(const Point &rStart, const Point &rEnd)
Definition: bmpacc3.cxx:101
std::optional< BitmapColor > mpFillColor
void SetFillColor()
Definition: bmpacc3.cxx:48
Point TopRight() const
tools::Long Right() const
bool ImplFastEraseBitmap(BitmapBuffer &rDst, const BitmapColor &rColor)
Definition: bmpfast.cxx:775