[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