bump product version to 7.2.5.1
[LibreOffice.git] / vcl / source / bitmap / BitmapWriteAccess.cxx
blobc7fb31cc1406a0faffeca50a6e8ac145718c4dfe
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <sal/config.h>
21 #include <sal/log.hxx>
22 #include <tools/debug.hxx>
24 #include <bitmap/BitmapWriteAccess.hxx>
25 #include <bitmap/bmpfast.hxx>
27 BitmapWriteAccess::BitmapWriteAccess(Bitmap& rBitmap)
28 : BitmapReadAccess(rBitmap, BitmapAccessMode::Write)
32 BitmapWriteAccess::~BitmapWriteAccess() {}
34 void BitmapWriteAccess::CopyScanline(tools::Long nY, const BitmapReadAccess& rReadAcc)
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!");
42 if ((GetScanlineFormat() == rReadAcc.GetScanlineFormat())
43 && (GetScanlineSize() >= rReadAcc.GetScanlineSize()))
45 memcpy(GetScanline(nY), rReadAcc.GetScanline(nY), rReadAcc.GetScanlineSize());
47 else
49 tools::Long nWidth = std::min(mpBuffer->mnWidth, rReadAcc.Width());
50 if (!ImplFastCopyScanline(nY, *ImplGetBitmapBuffer(), *rReadAcc.ImplGetBitmapBuffer()))
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));
60 void BitmapWriteAccess::CopyScanline(tools::Long nY, ConstScanline aSrcScanline,
61 ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
63 const ScanlineFormat nFormat = RemoveScanline(nSrcScanlineFormat);
65 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
66 DBG_ASSERT((HasPalette() && nFormat <= ScanlineFormat::N8BitPal)
67 || (!HasPalette() && nFormat > ScanlineFormat::N8BitPal),
68 "No copying possible between palette and non palette scanlines!");
70 const sal_uInt32 nCount = std::min(GetScanlineSize(), nSrcScanlineSize);
72 if (!nCount)
73 return;
75 if (GetScanlineFormat() == RemoveScanline(nSrcScanlineFormat))
76 memcpy(GetScanline(nY), aSrcScanline, nCount);
77 else
79 if (ImplFastCopyScanline(nY, *ImplGetBitmapBuffer(), aSrcScanline, nSrcScanlineFormat,
80 nSrcScanlineSize))
81 return;
83 DBG_ASSERT(nFormat != ScanlineFormat::N32BitTcMask,
84 "No support for pixel formats with color masks yet!");
85 FncGetPixel pFncGetPixel;
86 switch (nFormat)
88 case ScanlineFormat::N1BitMsbPal:
89 pFncGetPixel = GetPixelForN1BitMsbPal;
90 break;
91 case ScanlineFormat::N1BitLsbPal:
92 pFncGetPixel = GetPixelForN1BitLsbPal;
93 break;
94 case ScanlineFormat::N8BitPal:
95 pFncGetPixel = GetPixelForN8BitPal;
96 break;
97 case ScanlineFormat::N24BitTcBgr:
98 pFncGetPixel = GetPixelForN24BitTcBgr;
99 break;
100 case ScanlineFormat::N24BitTcRgb:
101 pFncGetPixel = GetPixelForN24BitTcRgb;
102 break;
103 case ScanlineFormat::N32BitTcAbgr:
104 if (Bitmap32IsPreMultipled())
105 pFncGetPixel = GetPixelForN32BitTcAbgr;
106 else
107 pFncGetPixel = GetPixelForN32BitTcXbgr;
108 break;
109 case ScanlineFormat::N32BitTcArgb:
110 if (Bitmap32IsPreMultipled())
111 pFncGetPixel = GetPixelForN32BitTcArgb;
112 else
113 pFncGetPixel = GetPixelForN32BitTcXrgb;
114 break;
115 case ScanlineFormat::N32BitTcBgra:
116 if (Bitmap32IsPreMultipled())
117 pFncGetPixel = GetPixelForN32BitTcBgra;
118 else
119 pFncGetPixel = GetPixelForN32BitTcBgrx;
120 break;
121 case ScanlineFormat::N32BitTcRgba:
122 if (Bitmap32IsPreMultipled())
123 pFncGetPixel = GetPixelForN32BitTcRgba;
124 else
125 pFncGetPixel = GetPixelForN32BitTcRgbx;
126 break;
127 case ScanlineFormat::N32BitTcMask:
128 pFncGetPixel = GetPixelForN32BitTcMask;
129 break;
131 default:
132 assert(false);
133 pFncGetPixel = nullptr;
134 break;
137 if (pFncGetPixel)
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));
147 void BitmapWriteAccess::SetLineColor(const Color& rColor)
149 if (rColor.GetAlpha() == 0)
151 mpLineColor.reset();
153 else
155 if (HasPalette())
157 mpLineColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
159 else
161 mpLineColor = BitmapColor(rColor);
166 void BitmapWriteAccess::SetFillColor() { mpFillColor.reset(); }
168 void BitmapWriteAccess::SetFillColor(const Color& rColor)
170 if (rColor.GetAlpha() == 0)
172 mpFillColor.reset();
174 else
176 if (HasPalette())
178 mpFillColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
180 else
182 mpFillColor = BitmapColor(rColor);
187 void BitmapWriteAccess::Erase(const Color& rColor)
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())
194 aColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
197 // try fast bitmap method first
198 if (ImplFastEraseBitmap(*mpBuffer, aColor))
199 return;
201 tools::Rectangle aRect(Point(), maBitmap.GetSizePixel());
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++)
214 Scanline pDestScanline = GetScanline(nY);
215 memcpy(pDestScanline, pFirstScanline, nScanlineSize);
219 void BitmapWriteAccess::DrawLine(const Point& rStart, const Point& rEnd)
221 if (!mpLineColor)
222 return;
224 const BitmapColor& rLineColor = *mpLineColor;
225 tools::Long nX, nY;
227 if (rStart.X() == rEnd.X())
229 // Vertical Line
230 const tools::Long nEndY = rEnd.Y();
232 nX = rStart.X();
233 nY = rStart.Y();
235 if (nEndY > nY)
237 for (; nY <= nEndY; nY++)
238 SetPixel(nY, nX, rLineColor);
240 else
242 for (; nY >= nEndY; nY--)
243 SetPixel(nY, nX, rLineColor);
246 else if (rStart.Y() == rEnd.Y())
248 // Horizontal Line
249 const tools::Long nEndX = rEnd.X();
251 nX = rStart.X();
252 nY = rStart.Y();
254 if (nEndX > nX)
256 for (; nX <= nEndX; nX++)
257 SetPixel(nY, nX, rLineColor);
259 else
261 for (; nX >= nEndX; nX--)
262 SetPixel(nY, nX, rLineColor);
265 else
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;
274 if (nDX >= nDY)
276 if (rStart.X() < rEnd.X())
278 nX1 = rStart.X();
279 nY1 = rStart.Y();
280 nX2 = rEnd.X();
281 nY2 = rEnd.Y();
283 else
285 nX1 = rEnd.X();
286 nY1 = rEnd.Y();
287 nX2 = rStart.X();
288 nY2 = rStart.Y();
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;
296 for (nX = nX1, nY = nY1; nX <= nX2; nX++)
298 SetPixel(nY, nX, rLineColor);
300 if (nD < 0)
301 nD += nDY2;
302 else
304 nD += nDYX;
306 if (bPos)
307 nY++;
308 else
309 nY--;
313 else
315 if (rStart.Y() < rEnd.Y())
317 nX1 = rStart.X();
318 nY1 = rStart.Y();
319 nX2 = rEnd.X();
320 nY2 = rEnd.Y();
322 else
324 nX1 = rEnd.X();
325 nY1 = rEnd.Y();
326 nX2 = rStart.X();
327 nY2 = rStart.Y();
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;
335 for (nX = nX1, nY = nY1; nY <= nY2; nY++)
337 SetPixel(nY, nX, rLineColor);
339 if (nD < 0)
340 nD += nDY2;
341 else
343 nD += nDYX;
345 if (bPos)
346 nX++;
347 else
348 nX--;
355 void BitmapWriteAccess::FillRect(const tools::Rectangle& rRect)
357 if (!mpFillColor)
358 return;
360 const BitmapColor& rFillColor = *mpFillColor;
361 tools::Rectangle aRect(Point(), maBitmap.GetSizePixel());
363 aRect.Intersection(rRect);
365 if (aRect.IsEmpty())
366 return;
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();
373 for (tools::Long nY = nStartY; nY <= nEndY; nY++)
375 Scanline pScanline = GetScanline(nY);
376 for (tools::Long nX = nStartX; nX <= nEndX; nX++)
378 SetPixelOnData(pScanline, nX, rFillColor);
383 void BitmapWriteAccess::DrawRect(const tools::Rectangle& rRect)
385 if (mpFillColor)
386 FillRect(rRect);
388 if (mpLineColor && (!mpFillColor || (*mpFillColor != *mpLineColor)))
390 DrawLine(rRect.TopLeft(), rRect.TopRight());
391 DrawLine(rRect.TopRight(), rRect.BottomRight());
392 DrawLine(rRect.BottomRight(), rRect.BottomLeft());
393 DrawLine(rRect.BottomLeft(), rRect.TopLeft());
397 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */