PDFProgressiveSearch.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. using System.Collections.Generic;
  2. using System.Diagnostics;
  3. using System.Text;
  4. using UnityEngine;
  5. using UnityEngine.EventSystems;
  6. namespace Paroxe.PdfRenderer
  7. {
  8. #if !UNITY_WEBGL
  9. /// <summary>
  10. /// Don't instantiate this class directly. Use the static method instead PDFProgressiveSearch.CreateSearch
  11. /// </summary>
  12. public class PDFProgressiveSearch : UIBehaviour
  13. {
  14. private bool m_AbortRequested;
  15. private int m_CurrentPage;
  16. private PDFDocument m_Document;
  17. private PDFSearchHandle.MatchOption m_Flags;
  18. private bool m_NewSearchRequested;
  19. private int m_PageCount;
  20. private byte[] m_Search;
  21. private IList<PDFSearchResult>[] m_SearchResults;
  22. private bool m_SearchStarted;
  23. private float m_TimeBudget = 0.50f;
  24. private int m_Total;
  25. public delegate void ProgressEventHandler(PDFProgressiveSearch sender, int total);
  26. public delegate void SearchFinishedEventHandler(PDFProgressiveSearch sender, IList<PDFSearchResult>[] searchResults);
  27. public event ProgressEventHandler OnProgressChanged;
  28. public event SearchFinishedEventHandler OnSearchFinished;
  29. /// <summary>
  30. /// Create a progressive search object within the scene.
  31. /// </summary>
  32. /// <param name="document"></param>
  33. /// <param name="timeBudget">Time budget per frame. The value must be metween 0.0f and 1.0f</param>
  34. /// <returns></returns>
  35. public static PDFProgressiveSearch CreateSearch(PDFDocument document, float timeBudget)
  36. {
  37. GameObject searchObject = new GameObject();
  38. searchObject.name = "PDFProgressiveSearch";
  39. PDFProgressiveSearch progressiveSearch = searchObject.AddComponent<PDFProgressiveSearch>();
  40. progressiveSearch.m_Document = document;
  41. progressiveSearch.m_TimeBudget = Mathf.Clamp01(timeBudget);
  42. return progressiveSearch;
  43. }
  44. /// <summary>
  45. /// Stop the current search request.
  46. /// </summary>
  47. public void Abort()
  48. {
  49. m_AbortRequested = true;
  50. }
  51. /// <summary>
  52. /// Start a new search and if a search is already started this method will stop it.
  53. /// </summary>
  54. /// <param name="search"></param>
  55. /// <param name="flags">PDFSearchHandle.MATCH_CASE, (PDFSearchHandle.MATCH_WHOLE_WORD or PDFSearchHandle.MATCH_CASE | PDFSearchHandle.MATCH_WHOLE_WORD)</param>
  56. public void StartSearch(string search, PDFSearchHandle.MatchOption flags)
  57. {
  58. if (string.IsNullOrEmpty(search.Trim()))
  59. m_Search = null;
  60. else
  61. m_Search = PDFLibrary.Encoding.GetBytes(search.Trim() + "\0");
  62. m_Flags = flags;
  63. m_PageCount = m_Document.GetPageCount();
  64. m_NewSearchRequested = true;
  65. }
  66. private void LateUpdate()
  67. {
  68. if (!m_SearchStarted && m_NewSearchRequested)
  69. {
  70. m_CurrentPage = 0;
  71. m_SearchResults = new IList<PDFSearchResult>[m_PageCount];
  72. m_NewSearchRequested = false;
  73. m_SearchStarted = true;
  74. m_AbortRequested = false;
  75. m_Total = 0;
  76. }
  77. if (m_SearchStarted)
  78. {
  79. if (m_AbortRequested)
  80. {
  81. m_SearchStarted = false;
  82. m_NewSearchRequested = false;
  83. m_AbortRequested = false;
  84. m_Total = 0;
  85. return;
  86. }
  87. if (m_NewSearchRequested)
  88. {
  89. m_CurrentPage = 0;
  90. m_SearchResults = new IList<PDFSearchResult>[m_PageCount];
  91. m_NewSearchRequested = false;
  92. m_Total = 0;
  93. }
  94. if (m_Search == null || m_Search.Length == 0)
  95. {
  96. m_SearchStarted = false;
  97. if (OnProgressChanged != null)
  98. {
  99. OnProgressChanged(this, 0);
  100. }
  101. var handler = OnSearchFinished;
  102. if (handler != null)
  103. {
  104. handler(this, null);
  105. }
  106. }
  107. else
  108. {
  109. Stopwatch timer = Stopwatch.StartNew();
  110. for (int i = m_CurrentPage; i < m_PageCount; ++i)
  111. {
  112. using (PDFTextPage textPage = m_Document.GetPage(i).GetTextPage())
  113. {
  114. IList<PDFSearchResult> searchResults = textPage.Search(m_Search, m_Flags);
  115. m_SearchResults[i] = searchResults;
  116. m_Total += searchResults.Count;
  117. ++m_CurrentPage;
  118. if (timer.ElapsedMilliseconds >=
  119. m_TimeBudget * 1000.0f * (1.0f / Mathf.Max(Application.targetFrameRate, 1.0f / Time.deltaTime)))
  120. {
  121. if (OnProgressChanged != null)
  122. {
  123. OnProgressChanged(this, m_Total);
  124. }
  125. break;
  126. }
  127. }
  128. }
  129. if (m_CurrentPage + 1 > m_PageCount)
  130. {
  131. m_SearchStarted = false;
  132. if (OnProgressChanged != null)
  133. {
  134. OnProgressChanged(this, m_Total);
  135. }
  136. var handler = OnSearchFinished;
  137. if (handler != null)
  138. {
  139. handler(this, m_SearchResults);
  140. }
  141. if (OnProgressChanged != null)
  142. {
  143. OnProgressChanged(this, m_Total);
  144. }
  145. }
  146. }
  147. }
  148. }
  149. }
  150. #endif
  151. }