[Libreoffice-commits] core.git: 2 commits - vcl/qa vcl/source
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Sat Apr 13 02:23:42 UTC 2019
vcl/qa/cppunit/BitmapTest.cxx | 94 ++++++++
vcl/source/bitmap/BitmapScaleSuperFilter.cxx | 287 +++++++++++++++++++++++----
2 files changed, 342 insertions(+), 39 deletions(-)
New commits:
commit 962debec1fa1c51d3eef96ca3432976ecfc0aa94
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Sat Apr 13 00:07:48 2019 +0900
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Apr 13 04:23:16 2019 +0200
tdf#124543 add functs. to scale 32bit bitmaps to BitmapScaleSuper
We still miss the support in other function however.
Change-Id: Ie87b588a9f8826242f4cff9d6671c98f3407f0e3
Reviewed-on: https://gerrit.libreoffice.org/70679
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
index a10bd8ccc17c..a09bad11e201 100644
--- a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
+++ b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
@@ -106,6 +106,67 @@ public:
}
};
+void scaleUp32bit(ScaleContext &rCtx, long nStartY, long nEndY)
+{
+ const int nColorComponents = 4;
+
+ const long nStartX = 0;
+ const long nEndX = rCtx.mnDestW - 1;
+
+ for (long nY = nStartY; nY <= nEndY; nY++)
+ {
+ long nTempY = rCtx.mpMapIY[nY];
+ long nTempFY = rCtx.mpMapFY[nY];
+
+ Scanline pLine0 = rCtx.mpSrc->GetScanline(nTempY+0);
+ Scanline pLine1 = rCtx.mpSrc->GetScanline(nTempY+1);
+ Scanline pScanDest = rCtx.mpDest->GetScanline(nY);
+
+ sal_uInt8 nComponent1[nColorComponents];
+ sal_uInt8 nComponent2[nColorComponents];
+
+ Scanline pColorPtr0;
+ Scanline pColorPtr1;
+
+ for (long nX = nStartX; nX <= nEndX; nX++)
+ {
+ long nTempX = rCtx.mpMapIX[nX];
+ long nTempFX = rCtx.mpMapFX[nX];
+
+ pColorPtr0 = pLine0 + nTempX * nColorComponents;
+ pColorPtr1 = pColorPtr0 + nColorComponents;
+
+ nComponent1[0] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+ pColorPtr0++; pColorPtr1++;
+ nComponent1[1] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+ pColorPtr0++; pColorPtr1++;
+ nComponent1[2] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+ pColorPtr0++; pColorPtr1++;
+ nComponent1[3] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+
+ pColorPtr0 = pLine1 + nTempX * nColorComponents;
+ pColorPtr1 = pColorPtr0 + nColorComponents;
+
+ nComponent2[0] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+ pColorPtr0++; pColorPtr1++;
+ nComponent2[1] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+ pColorPtr0++; pColorPtr1++;
+ nComponent2[2] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+ pColorPtr0++; pColorPtr1++;
+ nComponent2[3] = MAP(*pColorPtr0, *pColorPtr1, nTempFX);
+
+ *pScanDest = MAP(nComponent1[0], nComponent2[0], nTempFY);
+ pScanDest++;
+ *pScanDest = MAP(nComponent1[1], nComponent2[1], nTempFY);
+ pScanDest++;
+ *pScanDest = MAP(nComponent1[2], nComponent2[2], nTempFY);
+ pScanDest++;
+ *pScanDest = MAP(nComponent1[3], nComponent2[3], nTempFY);
+ pScanDest++;
+ }
+ }
+}
+
void scalePallete8bit(ScaleContext &rCtx, long nStartY, long nEndY)
{
const long nStartX = 0, nEndX = rCtx.mnDestW - 1;
@@ -296,6 +357,149 @@ void scaleNonPalleteGeneral(ScaleContext &rCtx, long nStartY, long nEndY)
}
}
+void scaleDown32bit(ScaleContext &rCtx, long nStartY, long nEndY)
+{
+ const int constColorComponents = 4;
+
+ const long nStartX = 0;
+ const long nEndX = rCtx.mnDestW - 1;
+ const long nMax = 1 << 7;
+
+ for (long nY = nStartY; nY <= nEndY; nY++)
+ {
+ long nTop = rCtx.mbVMirr ? (nY + 1) : nY;
+ long nBottom = rCtx.mbVMirr ? nY : (nY + 1);
+
+ long nLineStart;
+ long nLineRange;
+ if (nY == nEndY)
+ {
+ nLineStart = rCtx.mpMapIY[nY];
+ nLineRange = 0;
+ }
+ else
+ {
+ nLineStart = rCtx.mpMapIY[nTop];
+ nLineRange = (rCtx.mpMapIY[nBottom] == rCtx.mpMapIY[nTop]) ?
+ 1 : (rCtx.mpMapIY[nBottom] - rCtx.mpMapIY[nTop]);
+ }
+
+ Scanline pScanDest = rCtx.mpDest->GetScanline(nY);
+ for (long nX = nStartX; nX <= nEndX; nX++)
+ {
+ long nLeft = rCtx.mbHMirr ? (nX + 1) : nX;
+ long nRight = rCtx.mbHMirr ? nX : (nX + 1);
+
+ long nRowStart;
+ long nRowRange;
+ if (nX == nEndX)
+ {
+ nRowStart = rCtx.mpMapIX[nX];
+ nRowRange = 0;
+ }
+ else
+ {
+ nRowStart = rCtx.mpMapIX[nLeft];
+ nRowRange = (rCtx.mpMapIX[nRight] == rCtx.mpMapIX[nLeft]) ?
+ 1 : (rCtx.mpMapIX[nRight] - rCtx.mpMapIX[nLeft]);
+ }
+
+ long nSum1 = 0;
+ long nSum2 = 0;
+ long nSum3 = 0;
+ long nSum4 = 0;
+ long nTotalWeightY = 0;
+
+ for (long i = 0; i<= nLineRange; i++)
+ {
+ Scanline pTmpY = rCtx.mpSrc->GetScanline(nLineStart + i);
+ Scanline pTmpX = pTmpY + constColorComponents * nRowStart;
+
+ long nSumRow1 = 0;
+ long nSumRow2 = 0;
+ long nSumRow3 = 0;
+ long nSumRow4 = 0;
+ long nTotalWeightX = 0;
+
+ for (long j = 0; j <= nRowRange; j++)
+ {
+ if (nX == nEndX)
+ {
+ nSumRow1 += (*pTmpX) << 7; pTmpX++;
+ nSumRow2 += (*pTmpX) << 7; pTmpX++;
+ nSumRow3 += (*pTmpX) << 7; pTmpX++;
+ nSumRow4 += (*pTmpX) << 7; pTmpX++;
+ nTotalWeightX += 1 << 7;
+ }
+ else if(j == 0)
+ {
+ long nWeightX = nMax- rCtx.mpMapFX[nLeft];
+ nSumRow1 += (nWeightX * (*pTmpX)); pTmpX++;
+ nSumRow2 += (nWeightX * (*pTmpX)); pTmpX++;
+ nSumRow3 += (nWeightX * (*pTmpX)); pTmpX++;
+ nSumRow4 += (nWeightX * (*pTmpX)); pTmpX++;
+ nTotalWeightX += nWeightX;
+ }
+ else if ( nRowRange == j )
+ {
+ long nWeightX = rCtx.mpMapFX[ nRight ] ;
+ nSumRow1 += (nWeightX * (*pTmpX)); pTmpX++;
+ nSumRow2 += (nWeightX * (*pTmpX)); pTmpX++;
+ nSumRow3 += (nWeightX * (*pTmpX)); pTmpX++;
+ nSumRow4 += (nWeightX * (*pTmpX)); pTmpX++;
+ nTotalWeightX += nWeightX;
+ }
+ else
+ {
+ nSumRow1 += (*pTmpX) << 7; pTmpX++;
+ nSumRow2 += (*pTmpX) << 7; pTmpX++;
+ nSumRow3 += (*pTmpX) << 7; pTmpX++;
+ nSumRow4 += (*pTmpX) << 7; pTmpX++;
+ nTotalWeightX += 1 << 7;
+ }
+ }
+
+ long nWeightY = nMax;
+ if (nY == nEndY)
+ nWeightY = nMax;
+ else if (i == 0)
+ nWeightY = nMax - rCtx.mpMapFY[nTop];
+ else if (nLineRange == 1)
+ nWeightY = rCtx.mpMapFY[nTop];
+ else if (nLineRange == i)
+ nWeightY = rCtx.mpMapFY[nBottom];
+
+ if (nTotalWeightX)
+ {
+ nSumRow1 /= nTotalWeightX;
+ nSumRow2 /= nTotalWeightX;
+ nSumRow3 /= nTotalWeightX;
+ nSumRow4 /= nTotalWeightX;
+ }
+ nSum1 += nWeightY * nSumRow1;
+ nSum2 += nWeightY * nSumRow2;
+ nSum3 += nWeightY * nSumRow3;
+ nSum4 += nWeightY * nSumRow4;
+ nTotalWeightY += nWeightY;
+ }
+
+ if (nTotalWeightY)
+ {
+ nSum1 /= nTotalWeightY;
+ nSum2 /= nTotalWeightY;
+ nSum3 /= nTotalWeightY;
+ nSum4 /= nTotalWeightY;
+ }
+
+ // Write the calculated color components to the destination
+ *pScanDest = nSum1; pScanDest++;
+ *pScanDest = nSum2; pScanDest++;
+ *pScanDest = nSum3; pScanDest++;
+ *pScanDest = nSum4; pScanDest++;
+ }
+ }
+}
+
void scalePallete8bit2(ScaleContext &rCtx, long nStartY, long nEndY)
{
const long nStartX = 0, nEndX = rCtx.mnDestW - 1;
@@ -971,7 +1175,9 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const
{
Bitmap::ScopedReadAccess pReadAccess(aBitmap);
- Bitmap aOutBmp(Size(nDstW, nDstH), 24);
+ sal_Int16 nTargetBitcount = aBitmap.GetBitCount() == 32 ? 32 : 24;
+
+ Bitmap aOutBmp(Size(nDstW, nDstH), nTargetBitcount);
Size aOutSize = aOutBmp.GetSizePixel();
if (!aOutSize.Width() || !aOutSize.Height())
{
@@ -1019,6 +1225,12 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const
case ScanlineFormat::N24BitTcRgb:
pScaleRangeFn = bScaleUp ? scale24bitRGB : scale24bitRGB2;
break;
+ case ScanlineFormat::N32BitTcRgba:
+ case ScanlineFormat::N32BitTcBgra:
+ case ScanlineFormat::N32BitTcArgb:
+ case ScanlineFormat::N32BitTcAbgr:
+ pScaleRangeFn = bScaleUp ? scaleUp32bit : scaleDown32bit;
+ break;
default:
pScaleRangeFn = bScaleUp ? scaleNonPalleteGeneral
: scaleNonPalleteGeneral2;
@@ -1076,7 +1288,6 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const
pScaleRangeFn( aContext, nStartY, nEndY );
bRet = true;
-
aBitmap.AdaptBitCount(aOutBmp);
aBitmap = aOutBmp;
}
commit 9695896d8f0e3d4b2961c7a753c279a70f5bbaf2
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Fri Apr 12 22:38:13 2019 +0900
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sat Apr 13 04:23:01 2019 +0200
Improve multi-threaded scaling in BitmapScaleSuperFilter
The old approach was to calculate the number of stripes of the
bitmap per thread and later create the exact number tasks
(ScaleTask) as there are threads, where each task would process
stripes it had been given. This is needlesly complicated as the
job of a thread pool is to properly delegate the tasks between
threads. This was now changed so that we create one stripe
per ScaleTask and let the threadpool delegate the tasks to its
threads (that are available).
It also wanted to be clever and use the main thread to do the
work also, but it had a major flaw. The threadpool started to
process the tasks only when "waitUntilDone" method was called,
but the code first processed its slices and then called the
threadpool method to start processing. Because of this the
performance of scaling wasn't as good as it could be.
This behaviour was now changed so that the main thread isn't
involved in processing. It just creates the task, runs the
threadpool and waits until the tasks are finished.
Change-Id: I1e8c733bdbced8867d0a7f1190f0421a0cc3e067
Reviewed-on: https://gerrit.libreoffice.org/70668
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
Tested-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/vcl/qa/cppunit/BitmapTest.cxx b/vcl/qa/cppunit/BitmapTest.cxx
index 632a243af0cf..52abfb6c10e5 100644
--- a/vcl/qa/cppunit/BitmapTest.cxx
+++ b/vcl/qa/cppunit/BitmapTest.cxx
@@ -44,6 +44,7 @@ class BitmapTest : public CppUnit::TestFixture
void testN8Greyscale();
void testConvert();
void testScale();
+ void testScale2();
void testCRC();
void testGreyPalette();
void testCustom8BitPalette();
@@ -58,6 +59,7 @@ class BitmapTest : public CppUnit::TestFixture
CPPUNIT_TEST(testN4Greyscale);
CPPUNIT_TEST(testN8Greyscale);
CPPUNIT_TEST(testScale);
+ CPPUNIT_TEST(testScale2);
CPPUNIT_TEST(testCRC);
CPPUNIT_TEST(testGreyPalette);
CPPUNIT_TEST(testCustom8BitPalette);
@@ -453,6 +455,98 @@ void BitmapTest::testScale()
}
}
+bool checkBitmapColor(Bitmap const& rBitmap, Color const& rExpectedColor)
+{
+ bool bResult = true;
+ Bitmap aBitmap(rBitmap);
+ Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+ long nHeight = pReadAccess->Height();
+ long nWidth = pReadAccess->Width();
+ for (long y = 0; y < nHeight; ++y)
+ {
+ Scanline pScanlineRead = pReadAccess->GetScanline(y);
+ for (long x = 0; x < nWidth; ++x)
+ {
+ Color aColor = pReadAccess->GetPixelFromData(pScanlineRead, x).GetColor();
+ if (aColor != rExpectedColor)
+ bResult = false;
+ }
+ }
+
+ return bResult;
+}
+
+void BitmapTest::testScale2()
+{
+ const bool bExportBitmap(false);
+
+ Bitmap aBitmap24Bit(Size(4096, 4096), 24);
+ CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(24), aBitmap24Bit.GetBitCount());
+ Color aBitmapColor = COL_YELLOW;
+ {
+ BitmapScopedWriteAccess aWriteAccess(aBitmap24Bit);
+ aWriteAccess->Erase(aBitmapColor);
+ }
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_before.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(aBitmap24Bit, aStream);
+ }
+
+ // Scale - 65x65
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(4096), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(4096), aBitmap24Bit.GetSizePixel().Height());
+ Bitmap aScaledBitmap = aBitmap24Bit;
+ aScaledBitmap.Scale(Size(65, 65));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_after_65x65.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(aScaledBitmap, aStream);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(65), aScaledBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(65), aScaledBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
+
+ // Scale - 64x64
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(4096), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(4096), aBitmap24Bit.GetSizePixel().Height());
+ aScaledBitmap = aBitmap24Bit;
+ aScaledBitmap.Scale(Size(64, 64));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_after_64x64.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(aScaledBitmap, aStream);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(64), aScaledBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(64), aScaledBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
+
+ // Scale - 63x63
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(4096), aBitmap24Bit.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(4096), aBitmap24Bit.GetSizePixel().Height());
+ aScaledBitmap = aBitmap24Bit;
+ aScaledBitmap.Scale(Size(63, 63));
+
+ if (bExportBitmap)
+ {
+ SvFileStream aStream("scale_after_63x63.png", StreamMode::WRITE | StreamMode::TRUNC);
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+ rFilter.compressAsPNG(aScaledBitmap, aStream);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(63), aScaledBitmap.GetSizePixel().Width());
+ CPPUNIT_ASSERT_EQUAL(static_cast<long>(63), aScaledBitmap.GetSizePixel().Height());
+ CPPUNIT_ASSERT(checkBitmapColor(aScaledBitmap, aBitmapColor));
+}
+
typedef std::unordered_map<sal_uInt64, const char*> CRCHash;
void checkAndInsert(CRCHash& rHash, sal_uInt64 nCRC, const char* pLocation)
diff --git a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
index ea73f3b10a04..a10bd8ccc17c 100644
--- a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
+++ b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
@@ -77,29 +77,32 @@ struct ScaleContext {
}
};
-#define SCALE_THREAD_STRIP 32
-struct ScaleRangeContext {
- ScaleContext *mrCtx;
- long mnStartY, mnEndY;
- ScaleRangeContext( ScaleContext *rCtx, long nStartY )
- : mrCtx( rCtx ), mnStartY( nStartY ),
- mnEndY( nStartY + SCALE_THREAD_STRIP ) {}
-};
+constexpr long constScaleThreadStrip = 32;
-typedef void (*ScaleRangeFn)(ScaleContext &rCtx, long nStartY, long nEndY);
+typedef void (*ScaleRangeFn)(ScaleContext &rContext, long nStartY, long nEndY);
class ScaleTask : public comphelper::ThreadTask
{
- ScaleRangeFn const mpFn;
- std::vector< ScaleRangeContext > maStrips;
+ ScaleRangeFn const mpScaleRangeFunction;
+ ScaleContext& mrContext;
+ const long mnStartY;
+ const long mnEndY;
+
public:
- explicit ScaleTask( const std::shared_ptr<comphelper::ThreadTaskTag>& pTag, ScaleRangeFn pFn )
- : comphelper::ThreadTask(pTag), mpFn( pFn ) {}
- void push( ScaleRangeContext const &aRC ) { maStrips.push_back( aRC ); }
+ explicit ScaleTask(const std::shared_ptr<comphelper::ThreadTaskTag>& pTag,
+ ScaleRangeFn pScaleRangeFunction,
+ ScaleContext& rContext,
+ long nStartY, long nEndY)
+ : comphelper::ThreadTask(pTag)
+ , mpScaleRangeFunction(pScaleRangeFunction)
+ , mrContext(rContext)
+ , mnStartY(nStartY)
+ , mnEndY(nEndY)
+ {}
+
virtual void doWork() override
{
- for (auto const& strip : maStrips)
- mpFn( *(strip.mrCtx), strip.mnStartY, strip.mnEndY );
+ mpScaleRangeFunction(mrContext, mnStartY, mnEndY);
}
};
@@ -1026,12 +1029,11 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const
// We want to thread - only if there is a lot of work to do:
// We work hard when there is a large destination image, or
// A large source image.
- bool bHorizontalWork = pReadAccess->Width() > 512 || pWriteAccess->Width() > 512;
+ bool bHorizontalWork = pReadAccess->Height() >= 512 && pReadAccess->Width() >= 512;
bool bUseThreads = true;
static bool bDisableThreadedScaling = getenv ("VCL_NO_THREAD_SCALE");
- if ( bDisableThreadedScaling || !bHorizontalWork ||
- nEndY - nStartY < SCALE_THREAD_STRIP )
+ if (bDisableThreadedScaling || !bHorizontalWork)
{
SAL_INFO("vcl.gdi", "Scale in main thread");
bUseThreads = false;
@@ -1044,26 +1046,22 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const
// partition and queue work
comphelper::ThreadPool &rShared = comphelper::ThreadPool::getSharedOptimalPool();
std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
- sal_uInt32 nThreads = rShared.getWorkerCount();
- assert( nThreads > 0 );
- sal_uInt32 nStrips = ((nEndY - nStartY) + SCALE_THREAD_STRIP - 1) / SCALE_THREAD_STRIP;
- sal_uInt32 nStripsPerThread = nStrips / nThreads;
- SAL_INFO("vcl.gdi", "Scale in " << nStrips << " strips " << nStripsPerThread << " per thread we have " << nThreads << " CPU threads ");
- long nStripY = nStartY;
- for ( sal_uInt32 t = 0; t < nThreads - 1; t++ )
+
+ long nStripYStart = nStartY;
+ long nStripYEnd = nStripYStart + constScaleThreadStrip - 1;
+
+ while (nStripYEnd < nEndY)
{
- std::unique_ptr<ScaleTask> pTask(new ScaleTask( pTag, pScaleRangeFn ));
- for ( sal_uInt32 j = 0; j < nStripsPerThread; j++ )
- {
- ScaleRangeContext aRC( &aContext, nStripY );
- pTask->push( aRC );
- nStripY += SCALE_THREAD_STRIP;
- }
- rShared.pushTask( std::move(pTask) );
+ std::unique_ptr<ScaleTask> pTask(new ScaleTask(pTag, pScaleRangeFn, aContext, nStripYStart, nStripYEnd));
+ rShared.pushTask(std::move(pTask));
+ nStripYStart += constScaleThreadStrip;
+ nStripYEnd += constScaleThreadStrip;
+ }
+ if (nStripYStart <= nEndY)
+ {
+ std::unique_ptr<ScaleTask> pTask(new ScaleTask(pTag, pScaleRangeFn, aContext, nStripYStart, nEndY));
+ rShared.pushTask(std::move(pTask));
}
- // finish any remaining bits here
- pScaleRangeFn( aContext, nStripY, nEndY );
-
rShared.waitUntilDone(pTag);
SAL_INFO("vcl.gdi", "All threaded scaling tasks complete");
}
More information about the Libreoffice-commits
mailing list