From 4881fb10b123c870e1b46fba202cea696c17f1a9 Mon Sep 17 00:00:00 2001
From: Andrea Canciani <ranma42@gmail.com>
Date: Tue, 2 Nov 2010 13:39:43 +0100
Subject: [PATCH 3/3] Fix bug #30893

This is mostly a hack that avoids slow searches through the
words linked list.
---
 poppler/TextOutputDev.cc |   17 ++++++++++-------
 poppler/TextOutputDev.h  |    7 +++++++
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index b6b92bc..64ac71e 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -577,16 +577,19 @@ void TextPool::addWord(TextWord *word) {
     maxBaseIdx = newMaxBaseIdx;
   }
 
-  // insert the new word
-  w0 = NULL;
-  w1 = pool[wordBaseIdx - minBaseIdx];
-  for (; w1 && word->primaryCmp(w1) > 0; w0 = w1, w1 = w1->next) ;
-  word->next = w1;
-  if (w0) {
-    w0->next = word;
+  std::multiset<TextWord *>::iterator it = fastpool[wordBaseIdx].insert(word);
+  if (it != fastpool[wordBaseIdx].begin()) {
+    it--;
+    word->next = (*it)->next;
+    (*it)->next = word;
+    assert ((*it)->primaryCmp(word) <= 0);
   } else {
+    word->next = pool[wordBaseIdx - minBaseIdx];
     pool[wordBaseIdx - minBaseIdx] = word;
   }
+
+  if (word->next)
+    assert (word->primaryCmp(word->next) <= 0);
 }
 
 //------------------------------------------------------------------------
diff --git a/poppler/TextOutputDev.h b/poppler/TextOutputDev.h
index 47b134b..5aed710 100644
--- a/poppler/TextOutputDev.h
+++ b/poppler/TextOutputDev.h
@@ -35,6 +35,8 @@
 #include "GfxFont.h"
 #include "GfxState.h"
 #include "OutputDev.h"
+#include <set>
+#include <map>
 
 class GooString;
 class GooList;
@@ -207,6 +209,10 @@ private:
   friend class TextSelectionDumper;
 };
 
+struct wordCompare {
+  bool operator()(TextWord * const &a, TextWord * const &b) { return a->primaryCmp (b) < 0; }
+};
+
 //------------------------------------------------------------------------
 // TextPool
 //------------------------------------------------------------------------
@@ -230,6 +236,7 @@ private:
   int maxBaseIdx;		// max baseline bucket index
   TextWord **pool;		// array of linked lists, one for each
 				//   baseline value (multiple of 4 pts)
+  std::map<int, std::multiset<TextWord *, wordCompare> > fastpool; // same thing, but sets instead of lists
 
   friend class TextBlock;
   friend class TextPage;
-- 
1.7.0.4

