lok: Fix crash in paintPartTile() when the current view was destroyed.

Change-Id: I59b71ee6815cbcfa4c8b5f68ae6dc9299856d49e
Reviewed-on: https://gerrit.libreoffice.org/35494
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Jan Holesovsky <kendy@collabora.com>
This commit is contained in:
Jan Holesovsky 2017-03-20 23:05:22 +01:00
parent b6e62dc0dc
commit 89f5bb3cbb
2 changed files with 52 additions and 4 deletions

View file

@ -1824,11 +1824,27 @@ static void doc_paintPartTile(LibreOfficeKitDocument* pThis,
<< nTilePosX << ", " << nTilePosY << ") to ["
<< nCanvasWidth << "x" << nCanvasHeight << "]px" );
// Disable callbacks while we are painting.
LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis);
const int nOrigViewId = doc_getView(pThis);
int nOrigViewId = doc_getView(pThis);
if (nOrigViewId >= 0)
if (nOrigViewId < 0)
{
// tile painting always needs a SfxViewShell::Current(), but actually
// it does not really matter which one - all of them should paint the
// same thing.
int viewCount = doc_getViewsCount(pThis);
if (viewCount == 0)
return;
std::vector<int> viewIds(viewCount);
doc_getViewIds(pThis, viewIds.data(), viewCount);
nOrigViewId = viewIds[0];
doc_setView(pThis, nOrigViewId);
}
// Disable callbacks while we are painting.
if (nOrigViewId >= 0 && pDocument->mpCallbackFlushHandlers[nOrigViewId])
pDocument->mpCallbackFlushHandlers[nOrigViewId]->setPartTilePainting(true);
try
@ -1879,7 +1895,7 @@ static void doc_paintPartTile(LibreOfficeKitDocument* pThis,
// Nothing to do but restore the PartTilePainting flag.
}
if (nOrigViewId >= 0)
if (nOrigViewId >= 0 && pDocument->mpCallbackFlushHandlers[nOrigViewId])
pDocument->mpCallbackFlushHandlers[nOrigViewId]->setPartTilePainting(false);
}

View file

@ -72,6 +72,7 @@ public:
void testDocumentTypes( Office* pOffice );
void testImpressSlideNames( Office* pOffice );
void testCalcSheetNames( Office* pOffice );
void testPaintPartTile( Office* pOffice );
#if 0
void testOverlay( Office* pOffice );
#endif
@ -98,6 +99,7 @@ void TiledRenderingTest::runAllTests()
testDocumentTypes( pOffice.get() );
testImpressSlideNames( pOffice.get() );
testCalcSheetNames( pOffice.get() );
testPaintPartTile( pOffice.get() );
#if 0
testOverlay( pOffice.get() );
#endif
@ -186,6 +188,36 @@ void TiledRenderingTest::testCalcSheetNames( Office* pOffice )
CPPUNIT_ASSERT_EQUAL(std::string("Sheet3"), std::string(pDocument->getPartName(2)));
}
void TiledRenderingTest::testPaintPartTile(Office* pOffice)
{
const string sTextDocPath = m_sSrcRoot + "/libreofficekit/qa/data/blank_text.odt";
const string sTextLockFile = m_sSrcRoot +"/libreofficekit/qa/data/.~lock.blank_text.odt#";
// FIXME: same comment as below wrt lockfile removal.
remove(sTextLockFile.c_str());
std::unique_ptr<Document> pDocument(pOffice->documentLoad( sTextDocPath.c_str()));
CPPUNIT_ASSERT(pDocument.get());
CPPUNIT_ASSERT_EQUAL(LOK_DOCTYPE_TEXT, static_cast<LibreOfficeKitDocumentType>(pDocument->getDocumentType()));
// Create two views.
pDocument->getView();
pDocument->createView();
int nView2 = pDocument->getView();
// Destroy the current view
pDocument->destroyView(nView2);
int nCanvasWidth = 256;
int nCanvasHeight = 256;
std::vector<unsigned char> aBuffer(nCanvasWidth * nCanvasHeight * 4);
// And try to paintPartTile() - this used to crash when the current viewId
// was destroyed
pDocument->paintPartTile(aBuffer.data(), /*nPart=*/0, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, /*nTilePosY=*/0, /*nTileWidth=*/3840, /*nTileHeight=*/3840);
}
#if 0
static void dumpRGBABitmap( const OUString& rPath, const unsigned char* pBuffer,
const int nWidth, const int nHeight )