diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-02-02 10:47:22 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-02-02 14:15:47 +0100 |
commit | 8165c629be4e70ea188f3ccf2b8e913feec75da1 (patch) | |
tree | 0e4d32fa6dbf9bc2a7d8ee2c736d6753b5e24934 /vcl | |
parent | 26a22407124314479c99b44559ffbbce8c261fa5 (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.cxx | 50 |
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)) |