1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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());
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
);
75 if (GetScanlineFormat() == RemoveScanline(nSrcScanlineFormat
))
76 memcpy(GetScanline(nY
), aSrcScanline
, nCount
);
79 if (ImplFastCopyScanline(nY
, *ImplGetBitmapBuffer(), aSrcScanline
, nSrcScanlineFormat
,
83 DBG_ASSERT(nFormat
!= ScanlineFormat::N32BitTcMask
,
84 "No support for pixel formats with color masks yet!");
85 FncGetPixel pFncGetPixel
;
88 case ScanlineFormat::N1BitMsbPal
:
89 pFncGetPixel
= GetPixelForN1BitMsbPal
;
91 case ScanlineFormat::N1BitLsbPal
:
92 pFncGetPixel
= GetPixelForN1BitLsbPal
;
94 case ScanlineFormat::N8BitPal
:
95 pFncGetPixel
= GetPixelForN8BitPal
;
97 case ScanlineFormat::N24BitTcBgr
:
98 pFncGetPixel
= GetPixelForN24BitTcBgr
;
100 case ScanlineFormat::N24BitTcRgb
:
101 pFncGetPixel
= GetPixelForN24BitTcRgb
;
103 case ScanlineFormat::N32BitTcAbgr
:
104 if (Bitmap32IsPreMultipled())
105 pFncGetPixel
= GetPixelForN32BitTcAbgr
;
107 pFncGetPixel
= GetPixelForN32BitTcXbgr
;
109 case ScanlineFormat::N32BitTcArgb
:
110 if (Bitmap32IsPreMultipled())
111 pFncGetPixel
= GetPixelForN32BitTcArgb
;
113 pFncGetPixel
= GetPixelForN32BitTcXrgb
;
115 case ScanlineFormat::N32BitTcBgra
:
116 if (Bitmap32IsPreMultipled())
117 pFncGetPixel
= GetPixelForN32BitTcBgra
;
119 pFncGetPixel
= GetPixelForN32BitTcBgrx
;
121 case ScanlineFormat::N32BitTcRgba
:
122 if (Bitmap32IsPreMultipled())
123 pFncGetPixel
= GetPixelForN32BitTcRgba
;
125 pFncGetPixel
= GetPixelForN32BitTcRgbx
;
127 case ScanlineFormat::N32BitTcMask
:
128 pFncGetPixel
= GetPixelForN32BitTcMask
;
133 pFncGetPixel
= nullptr;
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)
157 mpLineColor
= BitmapColor(static_cast<sal_uInt8
>(GetBestPaletteIndex(rColor
)));
161 mpLineColor
= BitmapColor(rColor
);
166 void BitmapWriteAccess::SetFillColor() { mpFillColor
.reset(); }
168 void BitmapWriteAccess::SetFillColor(const Color
& rColor
)
170 if (rColor
.GetAlpha() == 0)
178 mpFillColor
= BitmapColor(static_cast<sal_uInt8
>(GetBestPaletteIndex(rColor
)));
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
;
194 aColor
= BitmapColor(static_cast<sal_uInt8
>(GetBestPaletteIndex(rColor
)));
197 // try fast bitmap method first
198 if (ImplFastEraseBitmap(*mpBuffer
, aColor
))
201 tools::Rectangle
aRect(Point(), maBitmap
.GetSizePixel());
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
)
224 const BitmapColor
& rLineColor
= *mpLineColor
;
227 if (rStart
.X() == rEnd
.X())
230 const tools::Long nEndY
= rEnd
.Y();
237 for (; nY
<= nEndY
; nY
++)
238 SetPixel(nY
, nX
, rLineColor
);
242 for (; nY
>= nEndY
; nY
--)
243 SetPixel(nY
, nX
, rLineColor
);
246 else if (rStart
.Y() == rEnd
.Y())
249 const tools::Long nEndX
= rEnd
.X();
256 for (; nX
<= nEndX
; nX
++)
257 SetPixel(nY
, nX
, rLineColor
);
261 for (; nX
>= nEndX
; nX
--)
262 SetPixel(nY
, nX
, rLineColor
);
267 const tools::Long nDX
= std::abs(rEnd
.X() - rStart
.X());
268 const tools::Long nDY
= std::abs(rEnd
.Y() - rStart
.Y());
276 if (rStart
.X() < rEnd
.X())
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
);
315 if (rStart
.Y() < rEnd
.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
);
355 void BitmapWriteAccess::FillRect(const tools::Rectangle
& rRect
)
360 const BitmapColor
& rFillColor
= *mpFillColor
;
361 tools::Rectangle
aRect(Point(), maBitmap
.GetSizePixel());
363 aRect
.Intersection(rRect
);
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
)
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: */