summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2022-02-02 10:47:22 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2022-02-02 14:15:47 +0100
commit8165c629be4e70ea188f3ccf2b8e913feec75da1 (patch)
tree0e4d32fa6dbf9bc2a7d8ee2c736d6753b5e24934 /vcl
parent26a22407124314479c99b44559ffbbce8c261fa5 (diff)
speed up bitmap rotation
(*) use more cache-dense temporary arrays (*) use float instead of double - I cannot see a difference in results (*) tools::Long->sal_Int32, we don't need more than 32-bits for x/y coordinates Change-Id: I81a1da573735f183a7d2a117f6170cf373433e4d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129324 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/source/bitmap/bitmappaint.cxx50
1 files changed, 23 insertions, 27 deletions
diff --git a/vcl/source/bitmap/bitmappaint.cxx b/vcl/source/bitmap/bitmappaint.cxx
index 034fd5738a2a..954820c761cc 100644
--- a/vcl/source/bitmap/bitmappaint.cxx
+++ b/vcl/source/bitmap/bitmappaint.cxx
@@ -367,45 +367,41 @@ bool Bitmap::Rotate(Degree10 nAngle10, const Color& rFillColor)
const double fSinAngle = sin(toRadians(nAngle10));
const double fXMin = aNewBound.Left();
const double fYMin = aNewBound.Top();
- const tools::Long nWidth = aSizePix.Width();
- const tools::Long nHeight = aSizePix.Height();
- const tools::Long nNewWidth = aNewSizePix.Width();
- const tools::Long nNewHeight = aNewSizePix.Height();
- tools::Long nX;
- tools::Long nY;
- tools::Long nRotX;
- tools::Long nRotY;
- std::unique_ptr<long[]> pCosX(new long[nNewWidth]);
- std::unique_ptr<long[]> pSinX(new long[nNewWidth]);
- std::unique_ptr<long[]> pCosY(new long[nNewHeight]);
- std::unique_ptr<long[]> pSinY(new long[nNewHeight]);
-
- for (nX = 0; nX < nNewWidth; nX++)
+ const sal_Int32 nWidth = aSizePix.Width();
+ const sal_Int32 nHeight = aSizePix.Height();
+ const sal_Int32 nNewWidth = aNewSizePix.Width();
+ const sal_Int32 nNewHeight = aNewSizePix.Height();
+ // we store alternating values of cos/sin. We do this instead of
+ // separate arrays to improve cache hit.
+ std::unique_ptr<sal_Int32[]> pCosSinX(new sal_Int32[nNewWidth * 2]);
+ std::unique_ptr<sal_Int32[]> pCosSinY(new sal_Int32[nNewHeight * 2]);
+
+ for (sal_Int32 nIdx = 0, nX = 0; nX < nNewWidth; nX++)
{
- const double fTmp = (fXMin + nX) * 64.;
+ const float fTmp = (fXMin + nX) * 64;
- pCosX[nX] = FRound(fCosAngle * fTmp);
- pSinX[nX] = FRound(fSinAngle * fTmp);
+ pCosSinX[nIdx++] = std::round(fCosAngle * fTmp);
+ pCosSinX[nIdx++] = std::round(fSinAngle * fTmp);
}
- for (nY = 0; nY < nNewHeight; nY++)
+ for (sal_Int32 nIdx = 0, nY = 0; nY < nNewHeight; nY++)
{
- const double fTmp = (fYMin + nY) * 64.;
+ const float fTmp = (fYMin + nY) * 64;
- pCosY[nY] = FRound(fCosAngle * fTmp);
- pSinY[nY] = FRound(fSinAngle * fTmp);
+ pCosSinY[nIdx++] = std::round(fCosAngle * fTmp);
+ pCosSinY[nIdx++] = std::round(fSinAngle * fTmp);
}
- for (nY = 0; nY < nNewHeight; nY++)
+ for (sal_Int32 nCosSinYIdx = 0, nY = 0; nY < nNewHeight; nY++)
{
- tools::Long nSinY = pSinY[nY];
- tools::Long nCosY = pCosY[nY];
+ sal_Int32 nSinY = pCosSinY[nCosSinYIdx++];
+ sal_Int32 nCosY = pCosSinY[nCosSinYIdx++];
Scanline pScanline = pWriteAcc->GetScanline(nY);
- for (nX = 0; nX < nNewWidth; nX++)
+ for (sal_Int32 nCosSinXIdx = 0, nX = 0; nX < nNewWidth; nX++)
{
- nRotX = (pCosX[nX] - nSinY) >> 6;
- nRotY = (pSinX[nX] + nCosY) >> 6;
+ sal_Int32 nRotX = (pCosSinX[nCosSinXIdx++] - nSinY) >> 6;
+ sal_Int32 nRotY = (pCosSinX[nCosSinXIdx++] + nCosY) >> 6;
if ((nRotX > -1) && (nRotX < nWidth) && (nRotY > -1)
&& (nRotY < nHeight))