desktop/qa/data/SearchIndexResultTest.odt   |binary
 desktop/qa/desktop_lib/test_desktop_lib.cxx |   49 +++++++++++++++++++++++-
 desktop/source/lib/init.cxx                 |   57 ++++++++++++++++++++++++++++
 include/LibreOfficeKit/LibreOfficeKit.h     |    6 ++
 include/LibreOfficeKit/LibreOfficeKit.hxx   |   16 +++++++
 include/vcl/ITiledRenderable.hxx            |    9 ++++
 sw/inc/unotxdoc.hxx                         |    3 +
 sw/source/uibase/uno/unotxdoc.cxx           |   25 ++++++++++++
 8 files changed, 164 insertions(+), 1 deletion(-)

New commits:
commit e1511ce551f27a5560600029193f076fd65ece17
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Jul 9 14:41:21 2021 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Fri Jul 30 08:22:19 2021 +0200

    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 <qui...@gmail.com>

diff --git a/desktop/qa/data/SearchIndexResultTest.odt 
b/desktop/qa/data/SearchIndexResultTest.odt
new file mode 100644
index 000000000000..58ed3a0f5447
Binary files /dev/null and b/desktop/qa/data/SearchIndexResultTest.odt 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");
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h 
b/include/LibreOfficeKit/LibreOfficeKit.h
index 82738d65ff93..8c9e0012552e 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -458,6 +458,12 @@ struct _LibreOfficeKitDocumentClass
     void (*sendFormFieldEvent) (LibreOfficeKitDocument* pThis,
                                 const char* pArguments);
 
+    /// @see lok::Document::renderSearchResult
+    bool (*renderSearchResult) (LibreOfficeKitDocument* pThis,
+                                const char* pSearchResult,
+                                unsigned char** pBitmapBuffer,
+                                int* pWidth, int* pHeight, size_t* pByteSize);
+
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx 
b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 06fe5abc19e2..b1d579849cbd 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -787,6 +787,22 @@ public:
         mpDoc->pClass->sendFormFieldEvent(mpDoc, pArguments);
     }
 
+    /**
+     * Render input search result to a bitmap buffer.
+     *
+     * @param pSearchResult payload containing the search result data
+     * @param pBitmapBuffer contains the bitmap; use free to deallocate.
+     * @param nWidth output bitmap width
+     * @param nHeight output bitmap height
+     * @param nByteSize output bitmap byte size
+     * @return true if successful
+     */
+    bool renderSearchResult(const char* pSearchResult, unsigned char** 
pBitmapBuffer,
+                            int* pWidth, int* pHeight, size_t* pByteSize)
+    {
+        return mpDoc->pClass->renderSearchResult(mpDoc, pSearchResult, 
pBitmapBuffer, pWidth, pHeight, pByteSize);
+    }
+
 #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
 };
 
diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx
index a1107e8a605a..c40c6f1cfb44 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -18,6 +18,7 @@
 #include <vcl/vclptr.hxx>
 #include <map>
 #include <com/sun/star/datatransfer/XTransferable.hpp>
+#include <basegfx/range/b2drange.hxx>
 
 namespace com::sun::star::beans { struct PropertyValue; }
 namespace com::sun::star::datatransfer::clipboard { class XClipboard; }
@@ -328,6 +329,14 @@ public:
     virtual void executeFromFieldEvent(const StringMap&)
     {
     }
+
+    /**
+     * Returns the rectangles of the input search result JSON
+     */
+    virtual std::vector<basegfx::B2DRange> getSearchResultRectangles(const 
char* /*pPayload*/)
+    {
+        return std::vector<basegfx::B2DRange>();
+    }
 };
 } // namespace vcl
 
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 79044005530a..02e2d8efb365 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -443,6 +443,9 @@ public:
     /// @see vcl::ITiledRenderable::executeFromFieldEvent().
     virtual void executeFromFieldEvent(const StringMap& aArguments) override;
 
+    /// @see vcl::ITiledRenderable::getSearchResultRectangles().
+    std::vector<basegfx::B2DRange> getSearchResultRectangles(const char* 
pPayload) override;
+
     // css::tiledrendering::XTiledRenderable
     virtual void SAL_CALL paintTile( const ::css::uno::Any& Parent, 
::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, 
::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) 
override;
 
diff --git a/sw/source/uibase/uno/unotxdoc.cxx 
b/sw/source/uibase/uno/unotxdoc.cxx
index b8f81db2f58b..8ea3697192b4 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -163,6 +163,8 @@
 #include <svx/svdpage.hxx>
 
 #include <IDocumentOutlineNodes.hxx>
+#include <SearchResultLocator.hxx>
+#include <boost/property_tree/json_parser.hpp>
 
 #define TWIPS_PER_PIXEL 15
 
@@ -3390,6 +3392,29 @@ void SwXTextDocument::executeFromFieldEvent(const 
StringMap& aArguments)
     }
 }
 
+std::vector<basegfx::B2DRange>
+SwXTextDocument::getSearchResultRectangles(const char* pPayload)
+{
+    std::vector<basegfx::B2DRange> aRectangles;
+
+    boost::property_tree::ptree aTree;
+    std::stringstream aStream(pPayload);
+    boost::property_tree::read_json(aStream, aTree);
+
+    sw::SearchIndexData aData;
+
+    aData.nNodeIndex = sal_uInt32(aTree.get<int>("node_index"));
+
+    SwDoc* pDoc = m_pDocShell->GetDoc();
+
+    sw::SearchResultLocator aLocator(pDoc);
+    sw::LocationResult aResult = aLocator.find(aData);
+    if (aResult.mbFound)
+        aRectangles = aResult.maRectangles;
+
+    return aRectangles;
+}
+
 int SwXTextDocument::getPart()
 {
     SolarMutexGuard aGuard;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to