summaryrefslogtreecommitdiff
path: root/desktop
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2021-07-09 14:41:21 +0900
committerTomaž Vajngerl <quikee@gmail.com>2021-07-30 08:22:19 +0200
commite1511ce551f27a5560600029193f076fd65ece17 (patch)
tree3f104ccdda4a63bbaf4d7745f56944ff4d0ad4b3 /desktop
parenteb31491b2a419ba7e67cc0a59a9b295fe49526e5 (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.odtbin0 -> 126871 bytes
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx49
-rw-r--r--desktop/source/lib/init.cxx57
3 files changed, 105 insertions, 1 deletions
diff --git a/desktop/qa/data/SearchIndexResultTest.odt b/desktop/qa/data/SearchIndexResultTest.odt
new file mode 100644
index 000000000000..58ed3a0f5447
--- /dev/null
+++ b/desktop/qa/data/SearchIndexResultTest.odt
Binary files differ
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");