diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2021-07-09 14:41:21 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2021-07-30 08:22:19 +0200 |
commit | e1511ce551f27a5560600029193f076fd65ece17 (patch) | |
tree | 3f104ccdda4a63bbaf4d7745f56944ff4d0ad4b3 /desktop | |
parent | eb31491b2a419ba7e67cc0a59a9b295fe49526e5 (diff) |
indexing: add LOKit API to render the search result into a bitmap
This adds a new LOKit API to render the search result into a bitmap
buffer. It combines the SearchResultLocator to get the location
inside the document of the search result (a series of rectangles)
and the existing LOKit paintTile API to render the result into
a bitmap (byte) buffer.
It also adds a LOKit test to show how the API is used and to render
a search result of a example document.
Change-Id: I4284d90188777fd28158d029daa04151e71022bb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118670
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/qa/data/SearchIndexResultTest.odt | bin | 0 -> 126871 bytes | |||
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 49 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 57 |
3 files changed, 105 insertions, 1 deletions
diff --git a/desktop/qa/data/SearchIndexResultTest.odt b/desktop/qa/data/SearchIndexResultTest.odt Binary files differnew file mode 100644 index 000000000000..58ed3a0f5447 --- /dev/null +++ b/desktop/qa/data/SearchIndexResultTest.odt diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 2a26b04dcfa0..dfbee77167b8 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -59,6 +59,8 @@ #include <svx/svxids.hrc> #include <cppunit/TestAssert.h> +#include <vcl/BitmapTools.hxx> +#include <vcl/pngwrite.hxx> #if USE_TLS_NSS #include <nss.h> @@ -205,6 +207,7 @@ public: void testMetricField(); void testMultiDocuments(); void testJumpCursor(); + void testRenderSearchResult(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -268,6 +271,7 @@ public: CPPUNIT_TEST(testMetricField); CPPUNIT_TEST(testMultiDocuments); CPPUNIT_TEST(testJumpCursor); + CPPUNIT_TEST(testRenderSearchResult); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -3103,6 +3107,48 @@ void DesktopLOKTest::testJumpCursor() comphelper::LibreOfficeKit::setTiledAnnotations(true); } +void DesktopLOKTest::testRenderSearchResult() +{ + constexpr const bool bDumpBitmap = false; + + LibLODocument_Impl* pDocument = loadDoc("SearchIndexResultTest.odt"); + pDocument->m_pDocumentClass->initializeForRendering(pDocument, "{}"); + + Scheduler::ProcessEventsToIdle(); + + unsigned char* pBuffer = nullptr; + OString aJSON = "{ \"node_index\" : 19 }"; + + int nWidth = 0; + int nHeight = 0; + size_t nByteSize = 0; + + bool bResult = pDocument->m_pDocumentClass->renderSearchResult(pDocument, aJSON.getStr(), &pBuffer, &nWidth, &nHeight, &nByteSize); + + CPPUNIT_ASSERT(bResult); + CPPUNIT_ASSERT(pBuffer); + + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(642, nWidth); + CPPUNIT_ASSERT_EQUAL(561, nHeight); + CPPUNIT_ASSERT_EQUAL(size_t(1440648), nByteSize); + + const sal_uInt8* pD = reinterpret_cast<const sal_uInt8*>(pBuffer); + BitmapEx aBitmap = vcl::bitmap::CreateFromData(pD, nWidth, nHeight, nWidth * 4, vcl::PixelFormat::N32_BPP, true, true); + + if (bDumpBitmap) + { + SvFileStream aStream("~/SearchResultBitmap.png", StreamMode::WRITE | StreamMode::TRUNC); + vcl::PNGWriter aPNGWriter(aBitmap); + aPNGWriter.Write(aStream); + } + CPPUNIT_ASSERT_EQUAL(tools::Long(642), aBitmap.GetSizePixel().Width()); + CPPUNIT_ASSERT_EQUAL(tools::Long(561), aBitmap.GetSizePixel().Height()); + + std::free(pBuffer); +} + namespace { constexpr size_t classOffset(int i) @@ -3200,10 +3246,11 @@ void DesktopLOKTest::testABI() CPPUNIT_ASSERT_EQUAL(documentClassOffset(59), offsetof(struct _LibreOfficeKitDocumentClass, completeFunction)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(60), offsetof(struct _LibreOfficeKitDocumentClass, setWindowTextSelection)); CPPUNIT_ASSERT_EQUAL(documentClassOffset(61), offsetof(struct _LibreOfficeKitDocumentClass, sendFormFieldEvent)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), offsetof(struct _LibreOfficeKitDocumentClass, renderSearchResult)); // Extending is fine, update this, and add new assert for the offsetof the // new method - CPPUNIT_ASSERT_EQUAL(documentClassOffset(62), sizeof(struct _LibreOfficeKitDocumentClass)); + CPPUNIT_ASSERT_EQUAL(documentClassOffset(63), sizeof(struct _LibreOfficeKitDocumentClass)); } CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index c9778d2b0f81..434b2bda81fa 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -43,6 +43,7 @@ #include <vcl/errinf.hxx> #include <vcl/lok.hxx> #include <o3tl/any.hxx> +#include <o3tl/unit_conversion.hxx> #include <osl/file.hxx> #include <osl/process.h> #include <osl/thread.h> @@ -1192,6 +1193,11 @@ static void doc_completeFunction(LibreOfficeKitDocument* pThis, const char*); static void doc_sendFormFieldEvent(LibreOfficeKitDocument* pThis, const char* pArguments); + +static bool doc_renderSearchResult(LibreOfficeKitDocument* pThis, + const char* pSearchResult, unsigned char** pBitmapBuffer, + int* pWidth, int* pHeight, size_t* pByteSize); + } // extern "C" namespace { @@ -1331,6 +1337,7 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone m_pDocumentClass->completeFunction = doc_completeFunction; m_pDocumentClass->sendFormFieldEvent = doc_sendFormFieldEvent; + m_pDocumentClass->renderSearchResult = doc_renderSearchResult; gDocumentClass = m_pDocumentClass; } @@ -5726,6 +5733,56 @@ static void doc_sendFormFieldEvent(LibreOfficeKitDocument* pThis, const char* pA pDoc->executeFromFieldEvent(aMap); } +static bool doc_renderSearchResult(LibreOfficeKitDocument* pThis, + const char* pSearchResult, unsigned char** pBitmapBuffer, + int* pWidth, int* pHeight, size_t* pByteSize) +{ + if (doc_getDocumentType(pThis) != LOK_DOCTYPE_TEXT) + return false; + + if (pBitmapBuffer == nullptr) + return false; + + if (!pSearchResult || pSearchResult[0] == '\0') + return false; + + ITiledRenderable* pDoc = getTiledRenderable(pThis); + if (!pDoc) + { + SetLastExceptionMsg("Document doesn't support tiled rendering"); + return false; + } + + auto aRectangleVector = pDoc->getSearchResultRectangles(pSearchResult); + + // combine into a rectangle union + basegfx::B2DRange aRangeUnion; + for (basegfx::B2DRange const & rRange : aRectangleVector) + { + aRangeUnion.expand(rRange); + } + + int aPixelWidth = o3tl::convert(aRangeUnion.getWidth(), o3tl::Length::twip, o3tl::Length::px); + int aPixelHeight = o3tl::convert(aRangeUnion.getHeight(), o3tl::Length::twip, o3tl::Length::px); + + size_t nByteSize = aPixelWidth * aPixelHeight * 4; + + *pWidth = aPixelWidth; + *pHeight = aPixelHeight; + *pByteSize = nByteSize; + + auto* pBuffer = static_cast<unsigned char*>(std::malloc(nByteSize)); + + doc_paintTile(pThis, pBuffer, + aPixelWidth, aPixelHeight, + aRangeUnion.getMinX(), aRangeUnion.getMinY(), + aRangeUnion.getWidth(), aRangeUnion.getHeight()); + + *pBitmapBuffer = pBuffer; + + return true; +} + static char* lo_getError (LibreOfficeKit *pThis) { comphelper::ProfileZone aZone("lo_getError"); |