1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #include <vcl/VectorGraphicSearch.hxx>
14 #include <vcl/filter/PDFiumLibrary.hxx>
15 #include <tools/UnitConversion.hxx>
17 #include <sal/config.h>
24 std::unique_ptr
<vcl::pdf::PDFiumDocument
>& mpPdfDocument
;
25 std::unique_ptr
<vcl::pdf::PDFiumPage
> mpPage
;
26 std::unique_ptr
<vcl::pdf::PDFiumTextPage
> mpTextPage
;
27 std::unique_ptr
<vcl::pdf::PDFiumSearchHandle
> mpSearchHandle
;
30 sal_Int32 mnPageIndex
;
32 OUString maSearchString
;
33 VectorGraphicSearchOptions maOptions
;
35 SearchContext(std::unique_ptr
<vcl::pdf::PDFiumDocument
>& pPdfDocument
, sal_Int32 nPageIndex
)
36 : mpPdfDocument(pPdfDocument
)
37 , mnPageIndex(nPageIndex
)
45 mpSearchHandle
.reset();
52 basegfx::B2DSize
getPageSize()
54 basegfx::B2DSize aSize
;
58 basegfx::B2DSize aPDFSize
= mpPdfDocument
->getPageSize(mnPageIndex
);
59 aSize
= basegfx::B2DSize(convertPointToMm100(aPDFSize
.getWidth()),
60 convertPointToMm100(aPDFSize
.getHeight()));
64 bool initialize(OUString
const& rSearchString
, VectorGraphicSearchOptions
const& rOptions
)
69 if (rSearchString
== maSearchString
)
73 mpSearchHandle
.reset();
81 maSearchString
= rSearchString
;
84 mpPage
= mpPdfDocument
->openPage(mnPageIndex
);
88 mpTextPage
= mpPage
->getTextPage();
92 // Index where to start to search. -1 => at the end
93 int nStartIndex
= maOptions
.meStartPosition
== SearchStartPosition::End
? -1 : 0;
95 if (mnCurrentIndex
>= 0)
96 nStartIndex
= mnCurrentIndex
;
98 // vcl::pdf::PDFFindFlags::MatchCase, vcl::pdf::PDFFindFlags::MatchWholeWord, vcl::pdf::PDFFindFlags::Consecutive
99 // vcl::pdf::PDFFindFlags::MatchCase - If not set, it will not match case by default.
100 // vcl::pdf::PDFFindFlags::MatchWholeWord - If not set, it will not match the whole word by default.
101 // vcl::pdf::PDFFindFlags::Consecutive - If not set, it will skip past the current match to look for the next match.
102 vcl::pdf::PDFFindFlags nSearchFlags
{};
103 if (maOptions
.mbMatchCase
)
104 nSearchFlags
|= vcl::pdf::PDFFindFlags::MatchCase
;
105 if (maOptions
.mbMatchWholeWord
)
106 nSearchFlags
|= vcl::pdf::PDFFindFlags::MatchWholeWord
;
108 mpSearchHandle
= mpTextPage
->findStart(maSearchString
, nSearchFlags
, nStartIndex
);
110 return mpSearchHandle
!= nullptr;
115 if (mpSearchHandle
&& mpSearchHandle
->findNext())
117 mnCurrentIndex
= index();
125 if (mpSearchHandle
&& mpSearchHandle
->findPrev())
127 mnCurrentIndex
= index();
136 return mpSearchHandle
->getSearchResultIndex();
143 return mpSearchHandle
->getSearchCount();
147 std::vector
<basegfx::B2DRectangle
> getTextRectangles()
149 std::vector
<basegfx::B2DRectangle
> aRectangles
;
151 if (!mpTextPage
|| !mpSearchHandle
)
154 int nIndex
= index();
162 double fPageHeight
= getPageSize().getHeight();
164 for (int nCount
= 0; nCount
< nSize
; nCount
++)
166 basegfx::B2DRectangle aRectangle
= mpTextPage
->getCharBox(nIndex
+ nCount
, fPageHeight
);
167 if (!aRectangle
.isEmpty())
169 aRectangles
.push_back(aRectangle
);
177 } // end anonymous namespace
179 class VectorGraphicSearch::Implementation
182 std::shared_ptr
<vcl::pdf::PDFium
> mpPDFium
;
183 std::unique_ptr
<vcl::pdf::PDFiumDocument
> mpPdfDocument
;
185 std::unique_ptr
<SearchContext
> mpSearchContext
;
188 : mpPDFium(vcl::pdf::PDFiumLibrary::get())
192 ~Implementation() { mpSearchContext
.reset(); }
195 VectorGraphicSearch::VectorGraphicSearch(Graphic aGraphic
)
196 : mpImplementation(std::make_unique
<VectorGraphicSearch::Implementation
>())
197 , maGraphic(std::move(aGraphic
))
201 VectorGraphicSearch::~VectorGraphicSearch() { mpImplementation
.reset(); }
203 bool VectorGraphicSearch::search(OUString
const& rSearchString
,
204 VectorGraphicSearchOptions
const& rOptions
)
206 if (!mpImplementation
->mpPDFium
)
211 if (!mpImplementation
->mpSearchContext
)
213 auto pData
= maGraphic
.getVectorGraphicData();
215 if (pData
&& pData
->getType() == VectorGraphicDataType::Pdf
)
217 if (searchPDF(pData
))
219 return mpImplementation
->mpSearchContext
->initialize(rSearchString
, rOptions
);
224 return mpImplementation
->mpSearchContext
->initialize(rSearchString
, rOptions
);
227 bool VectorGraphicSearch::searchPDF(std::shared_ptr
<VectorGraphicData
> const& rData
)
229 if (!mpImplementation
->mpPDFium
)
234 mpImplementation
->mpPdfDocument
= mpImplementation
->mpPDFium
->openDocument(
235 rData
->getBinaryDataContainer().getData(), rData
->getBinaryDataContainer().getSize(),
238 if (!mpImplementation
->mpPdfDocument
)
240 //TODO: Handle failure to load.
241 switch (mpImplementation
->mpPDFium
->getLastErrorCode())
243 case vcl::pdf::PDFErrorType::Success
:
245 case vcl::pdf::PDFErrorType::Unknown
:
247 case vcl::pdf::PDFErrorType::File
:
249 case vcl::pdf::PDFErrorType::Format
:
251 case vcl::pdf::PDFErrorType::Password
:
253 case vcl::pdf::PDFErrorType::Security
:
255 case vcl::pdf::PDFErrorType::Page
:
263 sal_Int32 nPageIndex
= std::max(rData
->getPageIndex(), sal_Int32(0));
265 mpImplementation
->mpSearchContext
.reset(
266 new SearchContext(mpImplementation
->mpPdfDocument
, nPageIndex
));
270 basegfx::B2DSize
VectorGraphicSearch::pageSize()
272 basegfx::B2DSize aSize
;
273 if (mpImplementation
->mpSearchContext
)
274 aSize
= mpImplementation
->mpSearchContext
->getPageSize();
278 bool VectorGraphicSearch::next()
280 if (mpImplementation
->mpSearchContext
)
281 return mpImplementation
->mpSearchContext
->next();
285 bool VectorGraphicSearch::previous()
287 if (mpImplementation
->mpSearchContext
)
288 return mpImplementation
->mpSearchContext
->previous();
292 int VectorGraphicSearch::index()
294 if (mpImplementation
->mpSearchContext
)
295 return mpImplementation
->mpSearchContext
->index();
299 std::vector
<basegfx::B2DRectangle
> VectorGraphicSearch::getTextRectangles()
301 if (mpImplementation
->mpSearchContext
)
302 return mpImplementation
->mpSearchContext
->getTextRectangles();
304 return std::vector
<basegfx::B2DRectangle
>();
307 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */