XRoom_Unity/Assets/Paroxe/PDFRenderer/API/Text/PDFProgressiveSearch.cs
2025-05-31 10:20:20 +03:30

189 lines
6.2 KiB
C#

using System.Collections.Generic;
using System.Diagnostics;
using Paroxe.PdfRenderer.Internal;
using UnityEngine;
using UnityEngine.EventSystems;
namespace Paroxe.PdfRenderer
{
#if !UNITY_WEBGL
/// <summary>
/// Don't instantiate this class directly. Use the static method instead PDFProgressiveSearch.CreateSearch
/// </summary>
public class PDFProgressiveSearch : UIBehaviour
{
private bool m_AbortRequested;
private int m_CurrentPage;
private PDFDocument m_Document;
private PDFSearchHandle.MatchOption m_Flags;
private bool m_NewSearchRequested;
private int m_PageCount;
private byte[] m_Search;
private IList<PDFSearchResult>[] m_SearchResults;
private bool m_SearchStarted;
private float m_TimeBudget = 0.50f;
private int m_Total;
public delegate void ProgressEventHandler(PDFProgressiveSearch sender, int total);
public delegate void SearchFinishedEventHandler(PDFProgressiveSearch sender, IList<PDFSearchResult>[] searchResults);
public event ProgressEventHandler OnProgressChanged;
public event SearchFinishedEventHandler OnSearchFinished;
/// <summary>
/// Create a progressive search object within the scene.
/// </summary>
/// <param name="document"></param>
/// <param name="timeBudget">Time budget per frame. The value must be metween 0.0f and 1.0f</param>
/// <returns></returns>
public static PDFProgressiveSearch CreateSearch(PDFDocument document, float timeBudget)
{
GameObject searchObject = new GameObject();
searchObject.name = "PDFProgressiveSearch";
PDFProgressiveSearch progressiveSearch = searchObject.AddComponent<PDFProgressiveSearch>();
progressiveSearch.m_Document = document;
progressiveSearch.m_TimeBudget = Mathf.Clamp01(timeBudget);
return progressiveSearch;
}
/// <summary>
/// Stop the current search request.
/// </summary>
public void Abort()
{
m_AbortRequested = true;
}
/// <summary>
/// Start a new search and if a search is already started this method will stop it.
/// </summary>
/// <param name="search"></param>
/// <param name="flags">PDFSearchHandle.MATCH_CASE, (PDFSearchHandle.MATCH_WHOLE_WORD or PDFSearchHandle.MATCH_CASE | PDFSearchHandle.MATCH_WHOLE_WORD)</param>
public void StartSearch(string search, PDFSearchHandle.MatchOption flags)
{
if (string.IsNullOrEmpty(search.Trim()))
m_Search = null;
else
m_Search = PDFLibrary.Encoding.GetBytes(search.Trim() + "\0");
m_Flags = flags;
m_PageCount = m_Document.GetPageCount();
m_NewSearchRequested = true;
}
private void LateUpdate()
{
if (!m_SearchStarted && m_NewSearchRequested)
{
m_CurrentPage = 0;
m_SearchResults = new IList<PDFSearchResult>[m_PageCount];
m_NewSearchRequested = false;
m_SearchStarted = true;
m_AbortRequested = false;
m_Total = 0;
}
if (m_SearchStarted)
{
if (m_AbortRequested)
{
m_SearchStarted = false;
m_NewSearchRequested = false;
m_AbortRequested = false;
m_Total = 0;
return;
}
if (m_NewSearchRequested)
{
m_CurrentPage = 0;
m_SearchResults = new IList<PDFSearchResult>[m_PageCount];
m_NewSearchRequested = false;
m_Total = 0;
}
if (m_Search == null || m_Search.Length == 0)
{
m_SearchStarted = false;
if (OnProgressChanged != null)
{
OnProgressChanged(this, 0);
}
SearchFinishedEventHandler handler = OnSearchFinished;
if (handler != null)
{
handler(this, null);
}
}
else
{
Stopwatch timer = Stopwatch.StartNew();
for (int i = m_CurrentPage; i < m_PageCount; ++i)
{
using (PDFPage page = m_Document.GetPage(i))
{
using (PDFTextPage textPage = page.GetTextPage())
{
IList<PDFSearchResult> searchResults = textPage.Search(m_Search, m_Flags);
m_SearchResults[i] = searchResults;
m_Total += searchResults.Count;
++m_CurrentPage;
if (timer.ElapsedMilliseconds >=
m_TimeBudget * 1000.0f * (1.0f / Mathf.Max(Application.targetFrameRate, 1.0f / Time.deltaTime)))
{
if (OnProgressChanged != null)
{
OnProgressChanged(this, m_Total);
}
break;
}
}
}
}
if (m_CurrentPage + 1 > m_PageCount)
{
m_SearchStarted = false;
if (OnProgressChanged != null)
{
OnProgressChanged(this, m_Total);
}
SearchFinishedEventHandler handler = OnSearchFinished;
if (handler != null)
{
handler(this, m_SearchResults);
}
if (OnProgressChanged != null)
{
OnProgressChanged(this, m_Total);
}
}
}
}
}
}
#endif
}