sw a11y: clang-format SidebarWinAccessible code
[LibreOffice.git] / vcl / source / graphic / VectorGraphicSearch.cxx
blobc2f624417552dbce3a181f84977e7303effc2d11
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 */
11 #include <utility>
12 #include <vcl/VectorGraphicSearch.hxx>
14 #include <vcl/filter/PDFiumLibrary.hxx>
15 #include <tools/UnitConversion.hxx>
17 #include <sal/config.h>
19 namespace
21 class SearchContext
23 private:
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;
29 public:
30 sal_Int32 mnPageIndex;
31 int mnCurrentIndex;
32 OUString maSearchString;
33 VectorGraphicSearchOptions maOptions;
35 SearchContext(std::unique_ptr<vcl::pdf::PDFiumDocument>& pPdfDocument, sal_Int32 nPageIndex)
36 : mpPdfDocument(pPdfDocument)
37 , mnPageIndex(nPageIndex)
38 , mnCurrentIndex(-1)
42 ~SearchContext()
44 if (mpSearchHandle)
45 mpSearchHandle.reset();
46 if (mpTextPage)
47 mpTextPage.reset();
48 if (mpPage)
49 mpPage.reset();
52 basegfx::B2DSize getPageSize()
54 basegfx::B2DSize aSize;
55 if (!mpPdfDocument)
56 return aSize;
58 basegfx::B2DSize aPDFSize = mpPdfDocument->getPageSize(mnPageIndex);
59 aSize = basegfx::B2DSize(convertPointToMm100(aPDFSize.getWidth()),
60 convertPointToMm100(aPDFSize.getHeight()));
61 return aSize;
64 bool initialize(OUString const& rSearchString, VectorGraphicSearchOptions const& rOptions)
66 if (!mpPdfDocument)
67 return false;
69 if (rSearchString == maSearchString)
70 return true;
72 if (mpSearchHandle)
73 mpSearchHandle.reset();
75 if (mpTextPage)
76 mpTextPage.reset();
78 if (mpPage)
79 mpPage.reset();
81 maSearchString = rSearchString;
82 maOptions = rOptions;
84 mpPage = mpPdfDocument->openPage(mnPageIndex);
85 if (!mpPage)
86 return false;
88 mpTextPage = mpPage->getTextPage();
89 if (!mpTextPage)
90 return false;
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;
113 bool next()
115 if (mpSearchHandle && mpSearchHandle->findNext())
117 mnCurrentIndex = index();
118 return true;
120 return false;
123 bool previous()
125 if (mpSearchHandle && mpSearchHandle->findPrev())
127 mnCurrentIndex = index();
128 return true;
130 return false;
133 int index()
135 if (mpSearchHandle)
136 return mpSearchHandle->getSearchResultIndex();
137 return -1;
140 int size()
142 if (mpSearchHandle)
143 return mpSearchHandle->getSearchCount();
144 return -1;
147 std::vector<basegfx::B2DRectangle> getTextRectangles()
149 std::vector<basegfx::B2DRectangle> aRectangles;
151 if (!mpTextPage || !mpSearchHandle)
152 return aRectangles;
154 int nIndex = index();
155 if (nIndex < 0)
156 return aRectangles;
158 int nSize = size();
159 if (nSize <= 0)
160 return aRectangles;
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);
173 return aRectangles;
177 } // end anonymous namespace
179 class VectorGraphicSearch::Implementation
181 public:
182 std::shared_ptr<vcl::pdf::PDFium> mpPDFium;
183 std::unique_ptr<vcl::pdf::PDFiumDocument> mpPdfDocument;
185 std::unique_ptr<SearchContext> mpSearchContext;
187 Implementation()
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)
208 return false;
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);
222 return false;
224 return mpImplementation->mpSearchContext->initialize(rSearchString, rOptions);
227 bool VectorGraphicSearch::searchPDF(std::shared_ptr<VectorGraphicData> const& rData)
229 if (!mpImplementation->mpPDFium)
231 return false;
234 mpImplementation->mpPdfDocument = mpImplementation->mpPDFium->openDocument(
235 rData->getBinaryDataContainer().getData(), rData->getBinaryDataContainer().getSize(),
236 OString());
238 if (!mpImplementation->mpPdfDocument)
240 //TODO: Handle failure to load.
241 switch (mpImplementation->mpPDFium->getLastErrorCode())
243 case vcl::pdf::PDFErrorType::Success:
244 break;
245 case vcl::pdf::PDFErrorType::Unknown:
246 break;
247 case vcl::pdf::PDFErrorType::File:
248 break;
249 case vcl::pdf::PDFErrorType::Format:
250 break;
251 case vcl::pdf::PDFErrorType::Password:
252 break;
253 case vcl::pdf::PDFErrorType::Security:
254 break;
255 case vcl::pdf::PDFErrorType::Page:
256 break;
257 default:
258 break;
260 return false;
263 sal_Int32 nPageIndex = std::max(rData->getPageIndex(), sal_Int32(0));
265 mpImplementation->mpSearchContext.reset(
266 new SearchContext(mpImplementation->mpPdfDocument, nPageIndex));
267 return true;
270 basegfx::B2DSize VectorGraphicSearch::pageSize()
272 basegfx::B2DSize aSize;
273 if (mpImplementation->mpSearchContext)
274 aSize = mpImplementation->mpSearchContext->getPageSize();
275 return aSize;
278 bool VectorGraphicSearch::next()
280 if (mpImplementation->mpSearchContext)
281 return mpImplementation->mpSearchContext->next();
282 return false;
285 bool VectorGraphicSearch::previous()
287 if (mpImplementation->mpSearchContext)
288 return mpImplementation->mpSearchContext->previous();
289 return false;
292 int VectorGraphicSearch::index()
294 if (mpImplementation->mpSearchContext)
295 return mpImplementation->mpSearchContext->index();
296 return -1;
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: */