tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / vcl / source / bitmap / BitmapWriteAccess.cxx
blob183a481e708ecdb9c0e0d26544dc451412934ee8
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 <vcl/BitmapWriteAccess.hxx>
25 #include <bitmap/bmpfast.hxx>
27 BitmapWriteAccess::BitmapWriteAccess(Bitmap& rBitmap)
28 : BitmapReadAccess(rBitmap, BitmapAccessMode::Write)
32 BitmapWriteAccess::BitmapWriteAccess(AlphaMask& rBitmap)
33 : BitmapReadAccess(rBitmap, BitmapAccessMode::Write)
37 BitmapWriteAccess::~BitmapWriteAccess() {}
39 void BitmapWriteAccess::CopyScanline(tools::Long nY, const BitmapReadAccess& rReadAcc)
41 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
42 SAL_WARN_IF(nY >= rReadAcc.Height(), "vcl", "y-coordinate in source out of range!");
43 SAL_WARN_IF((!HasPalette() || !rReadAcc.HasPalette())
44 && (HasPalette() || rReadAcc.HasPalette()),
45 "vcl", "No copying possible between palette bitmap and TC bitmap!");
47 if ((GetScanlineFormat() == rReadAcc.GetScanlineFormat())
48 && (GetScanlineSize() >= rReadAcc.GetScanlineSize()))
50 memcpy(GetScanline(nY), rReadAcc.GetScanline(nY), rReadAcc.GetScanlineSize());
52 else
54 tools::Long nWidth = std::min(mpBuffer->mnWidth, rReadAcc.Width());
55 if (!ImplFastCopyScanline(nY, *ImplGetBitmapBuffer(), *rReadAcc.ImplGetBitmapBuffer()))
57 Scanline pScanline = GetScanline(nY);
58 Scanline pScanlineRead = rReadAcc.GetScanline(nY);
59 for (tools::Long nX = 0; nX < nWidth; nX++)
60 SetPixelOnData(pScanline, nX, rReadAcc.GetPixelFromData(pScanlineRead, nX));
65 void BitmapWriteAccess::CopyScanline(tools::Long nY, ConstScanline aSrcScanline,
66 ScanlineFormat nSrcScanlineFormat, sal_uInt32 nSrcScanlineSize)
68 const ScanlineFormat eFormat = nSrcScanlineFormat;
70 assert(nY >= 0 && nY < mpBuffer->mnHeight && "y-coordinate in destination out of range!");
71 DBG_ASSERT((HasPalette() && eFormat <= ScanlineFormat::N8BitPal)
72 || (!HasPalette() && eFormat > ScanlineFormat::N8BitPal),
73 "No copying possible between palette and non palette scanlines!");
75 const sal_uInt32 nCount = std::min(GetScanlineSize(), nSrcScanlineSize);
77 if (!nCount)
78 return;
80 if (GetScanlineFormat() == eFormat)
81 memcpy(GetScanline(nY), aSrcScanline, nCount);
82 else
84 if (ImplFastCopyScanline(nY, *ImplGetBitmapBuffer(), aSrcScanline, nSrcScanlineFormat,
85 nSrcScanlineSize))
86 return;
88 DBG_ASSERT(eFormat != ScanlineFormat::N32BitTcMask,
89 "No support for pixel formats with color masks yet!");
90 FncGetPixel pFncGetPixel;
91 switch (eFormat)
93 case ScanlineFormat::N1BitMsbPal:
94 pFncGetPixel = GetPixelForN1BitMsbPal;
95 break;
96 case ScanlineFormat::N8BitPal:
97 pFncGetPixel = GetPixelForN8BitPal;
98 break;
99 case ScanlineFormat::N24BitTcBgr:
100 pFncGetPixel = GetPixelForN24BitTcBgr;
101 break;
102 case ScanlineFormat::N24BitTcRgb:
103 pFncGetPixel = GetPixelForN24BitTcRgb;
104 break;
105 case ScanlineFormat::N32BitTcAbgr:
106 if (Bitmap32IsPreMultipled())
107 pFncGetPixel = GetPixelForN32BitTcAbgr;
108 else
109 pFncGetPixel = GetPixelForN32BitTcXbgr;
110 break;
111 case ScanlineFormat::N32BitTcArgb:
112 if (Bitmap32IsPreMultipled())
113 pFncGetPixel = GetPixelForN32BitTcArgb;
114 else
115 pFncGetPixel = GetPixelForN32BitTcXrgb;
116 break;
117 case ScanlineFormat::N32BitTcBgra:
118 if (Bitmap32IsPreMultipled())
119 pFncGetPixel = GetPixelForN32BitTcBgra;
120 else
121 pFncGetPixel = GetPixelForN32BitTcBgrx;
122 break;
123 case ScanlineFormat::N32BitTcRgba:
124 if (Bitmap32IsPreMultipled())
125 pFncGetPixel = GetPixelForN32BitTcRgba;
126 else
127 pFncGetPixel = GetPixelForN32BitTcRgbx;
128 break;
129 case ScanlineFormat::N32BitTcMask:
130 pFncGetPixel = GetPixelForN32BitTcMask;
131 break;
133 default:
134 assert(false);
135 pFncGetPixel = nullptr;
136 break;
139 if (pFncGetPixel)
141 const ColorMask aDummyMask;
142 Scanline pScanline = GetScanline(nY);
143 for (tools::Long nX = 0, nWidth = mpBuffer->mnWidth; nX < nWidth; ++nX)
144 SetPixelOnData(pScanline, nX, pFncGetPixel(aSrcScanline, nX, aDummyMask));
149 void BitmapWriteAccess::SetLineColor(const Color& rColor)
151 if (rColor.GetAlpha() == 0)
153 mpLineColor.reset();
155 else
157 if (HasPalette())
159 mpLineColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
161 else
163 mpLineColor = BitmapColor(rColor);
168 void BitmapWriteAccess::SetFillColor() { mpFillColor.reset(); }
170 void BitmapWriteAccess::SetFillColor(const Color& rColor)
172 if (rColor.GetAlpha() == 0)
174 mpFillColor.reset();
176 else
178 if (HasPalette())
180 mpFillColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
182 else
184 mpFillColor = BitmapColor(rColor);
189 void BitmapWriteAccess::Erase(const Color& rColor)
191 // convert the color format from RGB to palette index if needed
192 // TODO: provide and use Erase( BitmapColor& method)
193 BitmapColor aColor = rColor;
194 if (HasPalette())
196 aColor = BitmapColor(static_cast<sal_uInt8>(GetBestPaletteIndex(rColor)));
199 // try fast bitmap method first
200 if (ImplFastEraseBitmap(*mpBuffer, aColor))
201 return;
203 tools::Rectangle aRect(Point(), maBitmap.GetSizePixel());
204 if (aRect.IsEmpty())
205 return;
206 // clear the bitmap by filling the first line pixel by pixel,
207 // then dup the first line over each other line
208 Scanline pFirstScanline = GetScanline(0);
209 const tools::Long nEndX = aRect.Right();
210 for (tools::Long nX = 0; nX <= nEndX; ++nX)
211 SetPixelOnData(pFirstScanline, nX, rColor);
212 const auto nScanlineSize = GetScanlineSize();
213 const tools::Long nEndY = aRect.Bottom();
214 for (tools::Long nY = 1; nY <= nEndY; nY++)
216 Scanline pDestScanline = GetScanline(nY);
217 memcpy(pDestScanline, pFirstScanline, nScanlineSize);
221 void BitmapWriteAccess::DrawLine(const Point& rStart, const Point& rEnd)
223 if (!mpLineColor)
224 return;
226 const BitmapColor& rLineColor = *mpLineColor;
227 tools::Long nX, nY;
229 if (rStart.X() == rEnd.X())
231 // Vertical Line
232 const tools::Long nEndY = rEnd.Y();
234 nX = rStart.X();
235 nY = rStart.Y();
237 if (nEndY > nY)
239 for (; nY <= nEndY; nY++)
240 SetPixel(nY, nX, rLineColor);
242 else
244 for (; nY >= nEndY; nY--)
245 SetPixel(nY, nX, rLineColor);
248 else if (rStart.Y() == rEnd.Y())
250 // Horizontal Line
251 const tools::Long nEndX = rEnd.X();
253 nX = rStart.X();
254 nY = rStart.Y();
256 if (nEndX > nX)
258 for (; nX <= nEndX; nX++)
259 SetPixel(nY, nX, rLineColor);
261 else
263 for (; nX >= nEndX; nX--)
264 SetPixel(nY, nX, rLineColor);
267 else
269 const tools::Long nDX = std::abs(rEnd.X() - rStart.X());
270 const tools::Long nDY = std::abs(rEnd.Y() - rStart.Y());
271 tools::Long nX1;
272 tools::Long nY1;
273 tools::Long nX2;
274 tools::Long nY2;
276 if (nDX >= nDY)
278 if (rStart.X() < rEnd.X())
280 nX1 = rStart.X();
281 nY1 = rStart.Y();
282 nX2 = rEnd.X();
283 nY2 = rEnd.Y();
285 else
287 nX1 = rEnd.X();
288 nY1 = rEnd.Y();
289 nX2 = rStart.X();
290 nY2 = rStart.Y();
293 const tools::Long nDYX = (nDY - nDX) << 1;
294 const tools::Long nDY2 = nDY << 1;
295 tools::Long nD = nDY2 - nDX;
296 bool bPos = nY1 < nY2;
298 for (nX = nX1, nY = nY1; nX <= nX2; nX++)
300 SetPixel(nY, nX, rLineColor);
302 if (nD < 0)
303 nD += nDY2;
304 else
306 nD += nDYX;
308 if (bPos)
309 nY++;
310 else
311 nY--;
315 else
317 if (rStart.Y() < rEnd.Y())
319 nX1 = rStart.X();
320 nY1 = rStart.Y();
321 nX2 = rEnd.X();
322 nY2 = rEnd.Y();
324 else
326 nX1 = rEnd.X();
327 nY1 = rEnd.Y();
328 nX2 = rStart.X();
329 nY2 = rStart.Y();
332 const tools::Long nDYX = (nDX - nDY) << 1;
333 const tools::Long nDY2 = nDX << 1;
334 tools::Long nD = nDY2 - nDY;
335 bool bPos = nX1 < nX2;
337 for (nX = nX1, nY = nY1; nY <= nY2; nY++)
339 SetPixel(nY, nX, rLineColor);
341 if (nD < 0)
342 nD += nDY2;
343 else
345 nD += nDYX;
347 if (bPos)
348 nX++;
349 else
350 nX--;
357 void BitmapWriteAccess::FillRect(const tools::Rectangle& rRect)
359 if (!mpFillColor)
360 return;
362 const BitmapColor& rFillColor = *mpFillColor;
363 tools::Rectangle aRect(Point(), maBitmap.GetSizePixel());
365 aRect.Intersection(rRect);
367 if (aRect.IsEmpty())
368 return;
370 const tools::Long nStartX = rRect.Left();
371 const tools::Long nStartY = rRect.Top();
372 const tools::Long nEndX = rRect.Right();
373 const tools::Long nEndY = rRect.Bottom();
375 for (tools::Long nY = nStartY; nY <= nEndY; nY++)
377 Scanline pScanline = GetScanline(nY);
378 for (tools::Long nX = nStartX; nX <= nEndX; nX++)
380 SetPixelOnData(pScanline, nX, rFillColor);
385 void BitmapWriteAccess::DrawRect(const tools::Rectangle& rRect)
387 if (mpFillColor)
388 FillRect(rRect);
390 if (mpLineColor && (!mpFillColor || (*mpFillColor != *mpLineColor)))
392 DrawLine(rRect.TopLeft(), rRect.TopRight());
393 DrawLine(rRect.TopRight(), rRect.BottomRight());
394 DrawLine(rRect.BottomRight(), rRect.BottomLeft());
395 DrawLine(rRect.BottomLeft(), rRect.TopLeft());
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */