diff --git a/src/api.js b/src/api.js
index 3d97dacd2..dee6c66b7 100644
--- a/src/api.js
+++ b/src/api.js
@@ -329,12 +329,18 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
       next();
     },
     /**
-     * Stub for future feature.
+     * @return {Promise} That is resolved with the a {string} that is the text
+     * content from the page.
      */
     getTextContent: function() {
       var promise = new PDFJS.Promise();
-      var textContent = 'page text'; // not implemented
-      promise.resolve(textContent);
+      this.transport.messageHandler.send('GetTextContent', {
+          pageIndex: this.pageNumber - 1
+        },
+        function textContentCallback(textContent) {
+          promise.resolve(textContent);
+        }
+      );
       return promise;
     },
     /**
diff --git a/src/core.js b/src/core.js
index 90a2c9733..5ce133dab 100644
--- a/src/core.js
+++ b/src/core.js
@@ -139,6 +139,7 @@ var Page = (function PageClosure() {
         // fetching items
         var streams = [];
         var i, n = content.length;
+        var streams = [];
         for (i = 0; i < n; ++i)
           streams.push(xref.fetchIfRef(content[i]));
         content = new StreamsSequenceStream(streams);
@@ -154,7 +155,53 @@ var Page = (function PageClosure() {
 
       return pe.getOperatorList(content, resources, dependency);
     },
+    extractTextContent: function Page_extractTextContent() {
+      if ('textContent' in this) {
+        // text content was extracted
+        return this.textContent;
+      }
 
+      var handler = {
+        on: function nullHandlerOn() {},
+        send: function nullHandlerSend() {}
+      };
+
+      var xref = this.xref;
+      var content = xref.fetchIfRef(this.content);
+      var resources = xref.fetchIfRef(this.resources);
+      if (isArray(content)) {
+        // fetching items
+        var i, n = content.length;
+        var streams = [];
+        for (i = 0; i < n; ++i)
+          streams.push(xref.fetchIfRef(content[i]));
+        content = new StreamsSequenceStream(streams);
+      } else if (isStream(content))
+        content.reset();
+
+      var pe = new PartialEvaluator(
+                     xref, handler, 'p' + this.pageNumber + '_');
+      var text = pe.getTextContent(content, resources);
+      return (this.textContent = text);
+    },
+
+    ensureFonts: function Page_ensureFonts(fonts, callback) {
+      this.stats.time('Font Loading');
+      // Convert the font names to the corresponding font obj.
+      for (var i = 0, ii = fonts.length; i < ii; i++) {
+        fonts[i] = this.objs.objs[fonts[i]].data;
+      }
+
+      // Load all the fonts
+      FontLoader.bind(
+        fonts,
+        function pageEnsureFontsFontObjs(fontObjs) {
+          this.stats.timeEnd('Font Loading');
+
+          callback.call(this);
+        }.bind(this)
+      );
+    },
     getLinks: function Page_getLinks() {
       var links = [];
       var annotations = pageGetAnnotations();
@@ -466,3 +513,4 @@ var PDFDocument = (function PDFDocumentClosure() {
 
   return PDFDocument;
 })();
+
diff --git a/src/evaluator.js b/src/evaluator.js
index e07394201..6cefa57db 100644
--- a/src/evaluator.js
+++ b/src/evaluator.js
@@ -153,8 +153,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
 
         font = xref.fetchIfRef(font) || fontRes.get(fontName);
         assertWellFormed(isDict(font));
-        ++self.objIdCounter;
-        if (!font.translated) {
+
+        if (!font.loadedName) {
+          ++self.objIdCounter;
           font.translated = self.translateFont(font, xref, resources,
                                                dependency);
           if (font.translated) {
@@ -474,6 +475,71 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
       return queue;
     },
 
+    getTextContent: function partialEvaluatorGetIRQueue(stream, resources) {
+
+      var self = this;
+      var xref = this.xref;
+
+      function handleSetFont(fontName, fontRef) {
+        var fontRes = resources.get('Font');
+
+        // TODO: TOASK: Is it possible to get here? If so, what does
+        // args[0].name should be like???
+        assert(fontRes, 'fontRes not available');
+
+        fontRes = xref.fetchIfRef(fontRes);
+        fontRef = fontRef || fontRes.get(fontName);
+        var font = xref.fetchIfRef(fontRef), tra;
+        assertWellFormed(isDict(font));
+        if (!font.translated) {
+          font.translated = self.translateFont(font, xref, resources);
+        }
+        return font;
+      }
+
+      resources = xref.fetchIfRef(resources) || new Dict();
+
+      var parser = new Parser(new Lexer(stream), false);
+      var res = resources;
+      var args = [], obj;
+
+      var text = '';
+      var font = null;
+      while (!isEOF(obj = parser.getObj())) {
+        if (isCmd(obj)) {
+          var cmd = obj.cmd;
+          switch (cmd) {
+            case 'Tf':
+              font = handleSetFont(args[0].name);
+              break;
+            case 'TJ':
+              var items = args[0];
+              for (var j = 0, jj = items.length; j < jj; j++) {
+                if (typeof items[j] === 'string') {
+                  text += fontCharsToUnicode(items[j],
+                    font.translated.properties);
+                } else if (items[j] < 0) {
+                  // making all negative offsets a space - better to have
+                  // a space in incorrect place than not have them at all
+                  text += ' ';
+                }
+              }
+              break;
+            case 'Tj':
+              text += fontCharsToUnicode(args[0], font.translated.properties);
+              break;
+          } // switch
+
+          args = [];
+        } else if (obj != null) {
+          assertWellFormed(args.length <= 33, 'Too many arguments');
+          args.push(obj);
+        }
+      }
+
+      return text;
+    },
+
     extractDataStructures: function
       partialEvaluatorExtractDataStructures(dict, baseDict,
                                             xref, properties) {
diff --git a/src/fonts.js b/src/fonts.js
index 7bd3ddd06..6881c7daf 100644
--- a/src/fonts.js
+++ b/src/fonts.js
@@ -753,6 +753,736 @@ function isSpecialUnicode(unicode) {
     unicode < kCmapGlyphOffset + kSizeOfGlyphArea);
 }
 
+// The normalization table is obtained by filtering the Unicode characters
+// database with <compat> entries.
+var NormalizedUnicodes = {
+  '\u00A8': '\u0020\u0308',
+  '\u00AF': '\u0020\u0304',
+  '\u00B4': '\u0020\u0301',
+  '\u00B5': '\u03BC',
+  '\u00B8': '\u0020\u0327',
+  '\u0132': '\u0049\u004A',
+  '\u0133': '\u0069\u006A',
+  '\u013F': '\u004C\u00B7',
+  '\u0140': '\u006C\u00B7',
+  '\u0149': '\u02BC\u006E',
+  '\u017F': '\u0073',
+  '\u01C4': '\u0044\u017D',
+  '\u01C5': '\u0044\u017E',
+  '\u01C6': '\u0064\u017E',
+  '\u01C7': '\u004C\u004A',
+  '\u01C8': '\u004C\u006A',
+  '\u01C9': '\u006C\u006A',
+  '\u01CA': '\u004E\u004A',
+  '\u01CB': '\u004E\u006A',
+  '\u01CC': '\u006E\u006A',
+  '\u01F1': '\u0044\u005A',
+  '\u01F2': '\u0044\u007A',
+  '\u01F3': '\u0064\u007A',
+  '\u02D8': '\u0020\u0306',
+  '\u02D9': '\u0020\u0307',
+  '\u02DA': '\u0020\u030A',
+  '\u02DB': '\u0020\u0328',
+  '\u02DC': '\u0020\u0303',
+  '\u02DD': '\u0020\u030B',
+  '\u037A': '\u0020\u0345',
+  '\u0384': '\u0020\u0301',
+  '\u03D0': '\u03B2',
+  '\u03D1': '\u03B8',
+  '\u03D2': '\u03A5',
+  '\u03D5': '\u03C6',
+  '\u03D6': '\u03C0',
+  '\u03F0': '\u03BA',
+  '\u03F1': '\u03C1',
+  '\u03F2': '\u03C2',
+  '\u03F4': '\u0398',
+  '\u03F5': '\u03B5',
+  '\u03F9': '\u03A3',
+  '\u0587': '\u0565\u0582',
+  '\u0675': '\u0627\u0674',
+  '\u0676': '\u0648\u0674',
+  '\u0677': '\u06C7\u0674',
+  '\u0678': '\u064A\u0674',
+  '\u0E33': '\u0E4D\u0E32',
+  '\u0EB3': '\u0ECD\u0EB2',
+  '\u0EDC': '\u0EAB\u0E99',
+  '\u0EDD': '\u0EAB\u0EA1',
+  '\u0F77': '\u0FB2\u0F81',
+  '\u0F79': '\u0FB3\u0F81',
+  '\u1E9A': '\u0061\u02BE',
+  '\u1FBD': '\u0020\u0313',
+  '\u1FBF': '\u0020\u0313',
+  '\u1FC0': '\u0020\u0342',
+  '\u1FFE': '\u0020\u0314',
+  '\u2002': '\u0020',
+  '\u2003': '\u0020',
+  '\u2004': '\u0020',
+  '\u2005': '\u0020',
+  '\u2006': '\u0020',
+  '\u2008': '\u0020',
+  '\u2009': '\u0020',
+  '\u200A': '\u0020',
+  '\u2017': '\u0020\u0333',
+  '\u2024': '\u002E',
+  '\u2025': '\u002E\u002E',
+  '\u2026': '\u002E\u002E\u002E',
+  '\u2033': '\u2032\u2032',
+  '\u2034': '\u2032\u2032\u2032',
+  '\u2036': '\u2035\u2035',
+  '\u2037': '\u2035\u2035\u2035',
+  '\u203C': '\u0021\u0021',
+  '\u203E': '\u0020\u0305',
+  '\u2047': '\u003F\u003F',
+  '\u2048': '\u003F\u0021',
+  '\u2049': '\u0021\u003F',
+  '\u2057': '\u2032\u2032\u2032\u2032',
+  '\u205F': '\u0020',
+  '\u20A8': '\u0052\u0073',
+  '\u2100': '\u0061\u002F\u0063',
+  '\u2101': '\u0061\u002F\u0073',
+  '\u2103': '\u00B0\u0043',
+  '\u2105': '\u0063\u002F\u006F',
+  '\u2106': '\u0063\u002F\u0075',
+  '\u2107': '\u0190',
+  '\u2109': '\u00B0\u0046',
+  '\u2116': '\u004E\u006F',
+  '\u2121': '\u0054\u0045\u004C',
+  '\u2135': '\u05D0',
+  '\u2136': '\u05D1',
+  '\u2137': '\u05D2',
+  '\u2138': '\u05D3',
+  '\u213B': '\u0046\u0041\u0058',
+  '\u2160': '\u0049',
+  '\u2161': '\u0049\u0049',
+  '\u2162': '\u0049\u0049\u0049',
+  '\u2163': '\u0049\u0056',
+  '\u2164': '\u0056',
+  '\u2165': '\u0056\u0049',
+  '\u2166': '\u0056\u0049\u0049',
+  '\u2167': '\u0056\u0049\u0049\u0049',
+  '\u2168': '\u0049\u0058',
+  '\u2169': '\u0058',
+  '\u216A': '\u0058\u0049',
+  '\u216B': '\u0058\u0049\u0049',
+  '\u216C': '\u004C',
+  '\u216D': '\u0043',
+  '\u216E': '\u0044',
+  '\u216F': '\u004D',
+  '\u2170': '\u0069',
+  '\u2171': '\u0069\u0069',
+  '\u2172': '\u0069\u0069\u0069',
+  '\u2173': '\u0069\u0076',
+  '\u2174': '\u0076',
+  '\u2175': '\u0076\u0069',
+  '\u2176': '\u0076\u0069\u0069',
+  '\u2177': '\u0076\u0069\u0069\u0069',
+  '\u2178': '\u0069\u0078',
+  '\u2179': '\u0078',
+  '\u217A': '\u0078\u0069',
+  '\u217B': '\u0078\u0069\u0069',
+  '\u217C': '\u006C',
+  '\u217D': '\u0063',
+  '\u217E': '\u0064',
+  '\u217F': '\u006D',
+  '\u222C': '\u222B\u222B',
+  '\u222D': '\u222B\u222B\u222B',
+  '\u222F': '\u222E\u222E',
+  '\u2230': '\u222E\u222E\u222E',
+  '\u2474': '\u0028\u0031\u0029',
+  '\u2475': '\u0028\u0032\u0029',
+  '\u2476': '\u0028\u0033\u0029',
+  '\u2477': '\u0028\u0034\u0029',
+  '\u2478': '\u0028\u0035\u0029',
+  '\u2479': '\u0028\u0036\u0029',
+  '\u247A': '\u0028\u0037\u0029',
+  '\u247B': '\u0028\u0038\u0029',
+  '\u247C': '\u0028\u0039\u0029',
+  '\u247D': '\u0028\u0031\u0030\u0029',
+  '\u247E': '\u0028\u0031\u0031\u0029',
+  '\u247F': '\u0028\u0031\u0032\u0029',
+  '\u2480': '\u0028\u0031\u0033\u0029',
+  '\u2481': '\u0028\u0031\u0034\u0029',
+  '\u2482': '\u0028\u0031\u0035\u0029',
+  '\u2483': '\u0028\u0031\u0036\u0029',
+  '\u2484': '\u0028\u0031\u0037\u0029',
+  '\u2485': '\u0028\u0031\u0038\u0029',
+  '\u2486': '\u0028\u0031\u0039\u0029',
+  '\u2487': '\u0028\u0032\u0030\u0029',
+  '\u2488': '\u0031\u002E',
+  '\u2489': '\u0032\u002E',
+  '\u248A': '\u0033\u002E',
+  '\u248B': '\u0034\u002E',
+  '\u248C': '\u0035\u002E',
+  '\u248D': '\u0036\u002E',
+  '\u248E': '\u0037\u002E',
+  '\u248F': '\u0038\u002E',
+  '\u2490': '\u0039\u002E',
+  '\u2491': '\u0031\u0030\u002E',
+  '\u2492': '\u0031\u0031\u002E',
+  '\u2493': '\u0031\u0032\u002E',
+  '\u2494': '\u0031\u0033\u002E',
+  '\u2495': '\u0031\u0034\u002E',
+  '\u2496': '\u0031\u0035\u002E',
+  '\u2497': '\u0031\u0036\u002E',
+  '\u2498': '\u0031\u0037\u002E',
+  '\u2499': '\u0031\u0038\u002E',
+  '\u249A': '\u0031\u0039\u002E',
+  '\u249B': '\u0032\u0030\u002E',
+  '\u249C': '\u0028\u0061\u0029',
+  '\u249D': '\u0028\u0062\u0029',
+  '\u249E': '\u0028\u0063\u0029',
+  '\u249F': '\u0028\u0064\u0029',
+  '\u24A0': '\u0028\u0065\u0029',
+  '\u24A1': '\u0028\u0066\u0029',
+  '\u24A2': '\u0028\u0067\u0029',
+  '\u24A3': '\u0028\u0068\u0029',
+  '\u24A4': '\u0028\u0069\u0029',
+  '\u24A5': '\u0028\u006A\u0029',
+  '\u24A6': '\u0028\u006B\u0029',
+  '\u24A7': '\u0028\u006C\u0029',
+  '\u24A8': '\u0028\u006D\u0029',
+  '\u24A9': '\u0028\u006E\u0029',
+  '\u24AA': '\u0028\u006F\u0029',
+  '\u24AB': '\u0028\u0070\u0029',
+  '\u24AC': '\u0028\u0071\u0029',
+  '\u24AD': '\u0028\u0072\u0029',
+  '\u24AE': '\u0028\u0073\u0029',
+  '\u24AF': '\u0028\u0074\u0029',
+  '\u24B0': '\u0028\u0075\u0029',
+  '\u24B1': '\u0028\u0076\u0029',
+  '\u24B2': '\u0028\u0077\u0029',
+  '\u24B3': '\u0028\u0078\u0029',
+  '\u24B4': '\u0028\u0079\u0029',
+  '\u24B5': '\u0028\u007A\u0029',
+  '\u2A0C': '\u222B\u222B\u222B\u222B',
+  '\u2A74': '\u003A\u003A\u003D',
+  '\u2A75': '\u003D\u003D',
+  '\u2A76': '\u003D\u003D\u003D',
+  '\u2E9F': '\u6BCD',
+  '\u2EF3': '\u9F9F',
+  '\u2F00': '\u4E00',
+  '\u2F01': '\u4E28',
+  '\u2F02': '\u4E36',
+  '\u2F03': '\u4E3F',
+  '\u2F04': '\u4E59',
+  '\u2F05': '\u4E85',
+  '\u2F06': '\u4E8C',
+  '\u2F07': '\u4EA0',
+  '\u2F08': '\u4EBA',
+  '\u2F09': '\u513F',
+  '\u2F0A': '\u5165',
+  '\u2F0B': '\u516B',
+  '\u2F0C': '\u5182',
+  '\u2F0D': '\u5196',
+  '\u2F0E': '\u51AB',
+  '\u2F0F': '\u51E0',
+  '\u2F10': '\u51F5',
+  '\u2F11': '\u5200',
+  '\u2F12': '\u529B',
+  '\u2F13': '\u52F9',
+  '\u2F14': '\u5315',
+  '\u2F15': '\u531A',
+  '\u2F16': '\u5338',
+  '\u2F17': '\u5341',
+  '\u2F18': '\u535C',
+  '\u2F19': '\u5369',
+  '\u2F1A': '\u5382',
+  '\u2F1B': '\u53B6',
+  '\u2F1C': '\u53C8',
+  '\u2F1D': '\u53E3',
+  '\u2F1E': '\u56D7',
+  '\u2F1F': '\u571F',
+  '\u2F20': '\u58EB',
+  '\u2F21': '\u5902',
+  '\u2F22': '\u590A',
+  '\u2F23': '\u5915',
+  '\u2F24': '\u5927',
+  '\u2F25': '\u5973',
+  '\u2F26': '\u5B50',
+  '\u2F27': '\u5B80',
+  '\u2F28': '\u5BF8',
+  '\u2F29': '\u5C0F',
+  '\u2F2A': '\u5C22',
+  '\u2F2B': '\u5C38',
+  '\u2F2C': '\u5C6E',
+  '\u2F2D': '\u5C71',
+  '\u2F2E': '\u5DDB',
+  '\u2F2F': '\u5DE5',
+  '\u2F30': '\u5DF1',
+  '\u2F31': '\u5DFE',
+  '\u2F32': '\u5E72',
+  '\u2F33': '\u5E7A',
+  '\u2F34': '\u5E7F',
+  '\u2F35': '\u5EF4',
+  '\u2F36': '\u5EFE',
+  '\u2F37': '\u5F0B',
+  '\u2F38': '\u5F13',
+  '\u2F39': '\u5F50',
+  '\u2F3A': '\u5F61',
+  '\u2F3B': '\u5F73',
+  '\u2F3C': '\u5FC3',
+  '\u2F3D': '\u6208',
+  '\u2F3E': '\u6236',
+  '\u2F3F': '\u624B',
+  '\u2F40': '\u652F',
+  '\u2F41': '\u6534',
+  '\u2F42': '\u6587',
+  '\u2F43': '\u6597',
+  '\u2F44': '\u65A4',
+  '\u2F45': '\u65B9',
+  '\u2F46': '\u65E0',
+  '\u2F47': '\u65E5',
+  '\u2F48': '\u66F0',
+  '\u2F49': '\u6708',
+  '\u2F4A': '\u6728',
+  '\u2F4B': '\u6B20',
+  '\u2F4C': '\u6B62',
+  '\u2F4D': '\u6B79',
+  '\u2F4E': '\u6BB3',
+  '\u2F4F': '\u6BCB',
+  '\u2F50': '\u6BD4',
+  '\u2F51': '\u6BDB',
+  '\u2F52': '\u6C0F',
+  '\u2F53': '\u6C14',
+  '\u2F54': '\u6C34',
+  '\u2F55': '\u706B',
+  '\u2F56': '\u722A',
+  '\u2F57': '\u7236',
+  '\u2F58': '\u723B',
+  '\u2F59': '\u723F',
+  '\u2F5A': '\u7247',
+  '\u2F5B': '\u7259',
+  '\u2F5C': '\u725B',
+  '\u2F5D': '\u72AC',
+  '\u2F5E': '\u7384',
+  '\u2F5F': '\u7389',
+  '\u2F60': '\u74DC',
+  '\u2F61': '\u74E6',
+  '\u2F62': '\u7518',
+  '\u2F63': '\u751F',
+  '\u2F64': '\u7528',
+  '\u2F65': '\u7530',
+  '\u2F66': '\u758B',
+  '\u2F67': '\u7592',
+  '\u2F68': '\u7676',
+  '\u2F69': '\u767D',
+  '\u2F6A': '\u76AE',
+  '\u2F6B': '\u76BF',
+  '\u2F6C': '\u76EE',
+  '\u2F6D': '\u77DB',
+  '\u2F6E': '\u77E2',
+  '\u2F6F': '\u77F3',
+  '\u2F70': '\u793A',
+  '\u2F71': '\u79B8',
+  '\u2F72': '\u79BE',
+  '\u2F73': '\u7A74',
+  '\u2F74': '\u7ACB',
+  '\u2F75': '\u7AF9',
+  '\u2F76': '\u7C73',
+  '\u2F77': '\u7CF8',
+  '\u2F78': '\u7F36',
+  '\u2F79': '\u7F51',
+  '\u2F7A': '\u7F8A',
+  '\u2F7B': '\u7FBD',
+  '\u2F7C': '\u8001',
+  '\u2F7D': '\u800C',
+  '\u2F7E': '\u8012',
+  '\u2F7F': '\u8033',
+  '\u2F80': '\u807F',
+  '\u2F81': '\u8089',
+  '\u2F82': '\u81E3',
+  '\u2F83': '\u81EA',
+  '\u2F84': '\u81F3',
+  '\u2F85': '\u81FC',
+  '\u2F86': '\u820C',
+  '\u2F87': '\u821B',
+  '\u2F88': '\u821F',
+  '\u2F89': '\u826E',
+  '\u2F8A': '\u8272',
+  '\u2F8B': '\u8278',
+  '\u2F8C': '\u864D',
+  '\u2F8D': '\u866B',
+  '\u2F8E': '\u8840',
+  '\u2F8F': '\u884C',
+  '\u2F90': '\u8863',
+  '\u2F91': '\u897E',
+  '\u2F92': '\u898B',
+  '\u2F93': '\u89D2',
+  '\u2F94': '\u8A00',
+  '\u2F95': '\u8C37',
+  '\u2F96': '\u8C46',
+  '\u2F97': '\u8C55',
+  '\u2F98': '\u8C78',
+  '\u2F99': '\u8C9D',
+  '\u2F9A': '\u8D64',
+  '\u2F9B': '\u8D70',
+  '\u2F9C': '\u8DB3',
+  '\u2F9D': '\u8EAB',
+  '\u2F9E': '\u8ECA',
+  '\u2F9F': '\u8F9B',
+  '\u2FA0': '\u8FB0',
+  '\u2FA1': '\u8FB5',
+  '\u2FA2': '\u9091',
+  '\u2FA3': '\u9149',
+  '\u2FA4': '\u91C6',
+  '\u2FA5': '\u91CC',
+  '\u2FA6': '\u91D1',
+  '\u2FA7': '\u9577',
+  '\u2FA8': '\u9580',
+  '\u2FA9': '\u961C',
+  '\u2FAA': '\u96B6',
+  '\u2FAB': '\u96B9',
+  '\u2FAC': '\u96E8',
+  '\u2FAD': '\u9751',
+  '\u2FAE': '\u975E',
+  '\u2FAF': '\u9762',
+  '\u2FB0': '\u9769',
+  '\u2FB1': '\u97CB',
+  '\u2FB2': '\u97ED',
+  '\u2FB3': '\u97F3',
+  '\u2FB4': '\u9801',
+  '\u2FB5': '\u98A8',
+  '\u2FB6': '\u98DB',
+  '\u2FB7': '\u98DF',
+  '\u2FB8': '\u9996',
+  '\u2FB9': '\u9999',
+  '\u2FBA': '\u99AC',
+  '\u2FBB': '\u9AA8',
+  '\u2FBC': '\u9AD8',
+  '\u2FBD': '\u9ADF',
+  '\u2FBE': '\u9B25',
+  '\u2FBF': '\u9B2F',
+  '\u2FC0': '\u9B32',
+  '\u2FC1': '\u9B3C',
+  '\u2FC2': '\u9B5A',
+  '\u2FC3': '\u9CE5',
+  '\u2FC4': '\u9E75',
+  '\u2FC5': '\u9E7F',
+  '\u2FC6': '\u9EA5',
+  '\u2FC7': '\u9EBB',
+  '\u2FC8': '\u9EC3',
+  '\u2FC9': '\u9ECD',
+  '\u2FCA': '\u9ED1',
+  '\u2FCB': '\u9EF9',
+  '\u2FCC': '\u9EFD',
+  '\u2FCD': '\u9F0E',
+  '\u2FCE': '\u9F13',
+  '\u2FCF': '\u9F20',
+  '\u2FD0': '\u9F3B',
+  '\u2FD1': '\u9F4A',
+  '\u2FD2': '\u9F52',
+  '\u2FD3': '\u9F8D',
+  '\u2FD4': '\u9F9C',
+  '\u2FD5': '\u9FA0',
+  '\u3036': '\u3012',
+  '\u3038': '\u5341',
+  '\u3039': '\u5344',
+  '\u303A': '\u5345',
+  '\u309B': '\u0020\u3099',
+  '\u309C': '\u0020\u309A',
+  '\u3131': '\u1100',
+  '\u3132': '\u1101',
+  '\u3133': '\u11AA',
+  '\u3134': '\u1102',
+  '\u3135': '\u11AC',
+  '\u3136': '\u11AD',
+  '\u3137': '\u1103',
+  '\u3138': '\u1104',
+  '\u3139': '\u1105',
+  '\u313A': '\u11B0',
+  '\u313B': '\u11B1',
+  '\u313C': '\u11B2',
+  '\u313D': '\u11B3',
+  '\u313E': '\u11B4',
+  '\u313F': '\u11B5',
+  '\u3140': '\u111A',
+  '\u3141': '\u1106',
+  '\u3142': '\u1107',
+  '\u3143': '\u1108',
+  '\u3144': '\u1121',
+  '\u3145': '\u1109',
+  '\u3146': '\u110A',
+  '\u3147': '\u110B',
+  '\u3148': '\u110C',
+  '\u3149': '\u110D',
+  '\u314A': '\u110E',
+  '\u314B': '\u110F',
+  '\u314C': '\u1110',
+  '\u314D': '\u1111',
+  '\u314E': '\u1112',
+  '\u314F': '\u1161',
+  '\u3150': '\u1162',
+  '\u3151': '\u1163',
+  '\u3152': '\u1164',
+  '\u3153': '\u1165',
+  '\u3154': '\u1166',
+  '\u3155': '\u1167',
+  '\u3156': '\u1168',
+  '\u3157': '\u1169',
+  '\u3158': '\u116A',
+  '\u3159': '\u116B',
+  '\u315A': '\u116C',
+  '\u315B': '\u116D',
+  '\u315C': '\u116E',
+  '\u315D': '\u116F',
+  '\u315E': '\u1170',
+  '\u315F': '\u1171',
+  '\u3160': '\u1172',
+  '\u3161': '\u1173',
+  '\u3162': '\u1174',
+  '\u3163': '\u1175',
+  '\u3164': '\u1160',
+  '\u3165': '\u1114',
+  '\u3166': '\u1115',
+  '\u3167': '\u11C7',
+  '\u3168': '\u11C8',
+  '\u3169': '\u11CC',
+  '\u316A': '\u11CE',
+  '\u316B': '\u11D3',
+  '\u316C': '\u11D7',
+  '\u316D': '\u11D9',
+  '\u316E': '\u111C',
+  '\u316F': '\u11DD',
+  '\u3170': '\u11DF',
+  '\u3171': '\u111D',
+  '\u3172': '\u111E',
+  '\u3173': '\u1120',
+  '\u3174': '\u1122',
+  '\u3175': '\u1123',
+  '\u3176': '\u1127',
+  '\u3177': '\u1129',
+  '\u3178': '\u112B',
+  '\u3179': '\u112C',
+  '\u317A': '\u112D',
+  '\u317B': '\u112E',
+  '\u317C': '\u112F',
+  '\u317D': '\u1132',
+  '\u317E': '\u1136',
+  '\u317F': '\u1140',
+  '\u3180': '\u1147',
+  '\u3181': '\u114C',
+  '\u3182': '\u11F1',
+  '\u3183': '\u11F2',
+  '\u3184': '\u1157',
+  '\u3185': '\u1158',
+  '\u3186': '\u1159',
+  '\u3187': '\u1184',
+  '\u3188': '\u1185',
+  '\u3189': '\u1188',
+  '\u318A': '\u1191',
+  '\u318B': '\u1192',
+  '\u318C': '\u1194',
+  '\u318D': '\u119E',
+  '\u318E': '\u11A1',
+  '\u3200': '\u0028\u1100\u0029',
+  '\u3201': '\u0028\u1102\u0029',
+  '\u3202': '\u0028\u1103\u0029',
+  '\u3203': '\u0028\u1105\u0029',
+  '\u3204': '\u0028\u1106\u0029',
+  '\u3205': '\u0028\u1107\u0029',
+  '\u3206': '\u0028\u1109\u0029',
+  '\u3207': '\u0028\u110B\u0029',
+  '\u3208': '\u0028\u110C\u0029',
+  '\u3209': '\u0028\u110E\u0029',
+  '\u320A': '\u0028\u110F\u0029',
+  '\u320B': '\u0028\u1110\u0029',
+  '\u320C': '\u0028\u1111\u0029',
+  '\u320D': '\u0028\u1112\u0029',
+  '\u320E': '\u0028\u1100\u1161\u0029',
+  '\u320F': '\u0028\u1102\u1161\u0029',
+  '\u3210': '\u0028\u1103\u1161\u0029',
+  '\u3211': '\u0028\u1105\u1161\u0029',
+  '\u3212': '\u0028\u1106\u1161\u0029',
+  '\u3213': '\u0028\u1107\u1161\u0029',
+  '\u3214': '\u0028\u1109\u1161\u0029',
+  '\u3215': '\u0028\u110B\u1161\u0029',
+  '\u3216': '\u0028\u110C\u1161\u0029',
+  '\u3217': '\u0028\u110E\u1161\u0029',
+  '\u3218': '\u0028\u110F\u1161\u0029',
+  '\u3219': '\u0028\u1110\u1161\u0029',
+  '\u321A': '\u0028\u1111\u1161\u0029',
+  '\u321B': '\u0028\u1112\u1161\u0029',
+  '\u321C': '\u0028\u110C\u116E\u0029',
+  '\u321D': '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029',
+  '\u321E': '\u0028\u110B\u1169\u1112\u116E\u0029',
+  '\u3220': '\u0028\u4E00\u0029',
+  '\u3221': '\u0028\u4E8C\u0029',
+  '\u3222': '\u0028\u4E09\u0029',
+  '\u3223': '\u0028\u56DB\u0029',
+  '\u3224': '\u0028\u4E94\u0029',
+  '\u3225': '\u0028\u516D\u0029',
+  '\u3226': '\u0028\u4E03\u0029',
+  '\u3227': '\u0028\u516B\u0029',
+  '\u3228': '\u0028\u4E5D\u0029',
+  '\u3229': '\u0028\u5341\u0029',
+  '\u322A': '\u0028\u6708\u0029',
+  '\u322B': '\u0028\u706B\u0029',
+  '\u322C': '\u0028\u6C34\u0029',
+  '\u322D': '\u0028\u6728\u0029',
+  '\u322E': '\u0028\u91D1\u0029',
+  '\u322F': '\u0028\u571F\u0029',
+  '\u3230': '\u0028\u65E5\u0029',
+  '\u3231': '\u0028\u682A\u0029',
+  '\u3232': '\u0028\u6709\u0029',
+  '\u3233': '\u0028\u793E\u0029',
+  '\u3234': '\u0028\u540D\u0029',
+  '\u3235': '\u0028\u7279\u0029',
+  '\u3236': '\u0028\u8CA1\u0029',
+  '\u3237': '\u0028\u795D\u0029',
+  '\u3238': '\u0028\u52B4\u0029',
+  '\u3239': '\u0028\u4EE3\u0029',
+  '\u323A': '\u0028\u547C\u0029',
+  '\u323B': '\u0028\u5B66\u0029',
+  '\u323C': '\u0028\u76E3\u0029',
+  '\u323D': '\u0028\u4F01\u0029',
+  '\u323E': '\u0028\u8CC7\u0029',
+  '\u323F': '\u0028\u5354\u0029',
+  '\u3240': '\u0028\u796D\u0029',
+  '\u3241': '\u0028\u4F11\u0029',
+  '\u3242': '\u0028\u81EA\u0029',
+  '\u3243': '\u0028\u81F3\u0029',
+  '\u32C0': '\u0031\u6708',
+  '\u32C1': '\u0032\u6708',
+  '\u32C2': '\u0033\u6708',
+  '\u32C3': '\u0034\u6708',
+  '\u32C4': '\u0035\u6708',
+  '\u32C5': '\u0036\u6708',
+  '\u32C6': '\u0037\u6708',
+  '\u32C7': '\u0038\u6708',
+  '\u32C8': '\u0039\u6708',
+  '\u32C9': '\u0031\u0030\u6708',
+  '\u32CA': '\u0031\u0031\u6708',
+  '\u32CB': '\u0031\u0032\u6708',
+  '\u3358': '\u0030\u70B9',
+  '\u3359': '\u0031\u70B9',
+  '\u335A': '\u0032\u70B9',
+  '\u335B': '\u0033\u70B9',
+  '\u335C': '\u0034\u70B9',
+  '\u335D': '\u0035\u70B9',
+  '\u335E': '\u0036\u70B9',
+  '\u335F': '\u0037\u70B9',
+  '\u3360': '\u0038\u70B9',
+  '\u3361': '\u0039\u70B9',
+  '\u3362': '\u0031\u0030\u70B9',
+  '\u3363': '\u0031\u0031\u70B9',
+  '\u3364': '\u0031\u0032\u70B9',
+  '\u3365': '\u0031\u0033\u70B9',
+  '\u3366': '\u0031\u0034\u70B9',
+  '\u3367': '\u0031\u0035\u70B9',
+  '\u3368': '\u0031\u0036\u70B9',
+  '\u3369': '\u0031\u0037\u70B9',
+  '\u336A': '\u0031\u0038\u70B9',
+  '\u336B': '\u0031\u0039\u70B9',
+  '\u336C': '\u0032\u0030\u70B9',
+  '\u336D': '\u0032\u0031\u70B9',
+  '\u336E': '\u0032\u0032\u70B9',
+  '\u336F': '\u0032\u0033\u70B9',
+  '\u3370': '\u0032\u0034\u70B9',
+  '\u33E0': '\u0031\u65E5',
+  '\u33E1': '\u0032\u65E5',
+  '\u33E2': '\u0033\u65E5',
+  '\u33E3': '\u0034\u65E5',
+  '\u33E4': '\u0035\u65E5',
+  '\u33E5': '\u0036\u65E5',
+  '\u33E6': '\u0037\u65E5',
+  '\u33E7': '\u0038\u65E5',
+  '\u33E8': '\u0039\u65E5',
+  '\u33E9': '\u0031\u0030\u65E5',
+  '\u33EA': '\u0031\u0031\u65E5',
+  '\u33EB': '\u0031\u0032\u65E5',
+  '\u33EC': '\u0031\u0033\u65E5',
+  '\u33ED': '\u0031\u0034\u65E5',
+  '\u33EE': '\u0031\u0035\u65E5',
+  '\u33EF': '\u0031\u0036\u65E5',
+  '\u33F0': '\u0031\u0037\u65E5',
+  '\u33F1': '\u0031\u0038\u65E5',
+  '\u33F2': '\u0031\u0039\u65E5',
+  '\u33F3': '\u0032\u0030\u65E5',
+  '\u33F4': '\u0032\u0031\u65E5',
+  '\u33F5': '\u0032\u0032\u65E5',
+  '\u33F6': '\u0032\u0033\u65E5',
+  '\u33F7': '\u0032\u0034\u65E5',
+  '\u33F8': '\u0032\u0035\u65E5',
+  '\u33F9': '\u0032\u0036\u65E5',
+  '\u33FA': '\u0032\u0037\u65E5',
+  '\u33FB': '\u0032\u0038\u65E5',
+  '\u33FC': '\u0032\u0039\u65E5',
+  '\u33FD': '\u0033\u0030\u65E5',
+  '\u33FE': '\u0033\u0031\u65E5',
+  '\uFB00': '\u0066\u0066',
+  '\uFB01': '\u0066\u0069',
+  '\uFB02': '\u0066\u006C',
+  '\uFB03': '\u0066\u0066\u0069',
+  '\uFB04': '\u0066\u0066\u006C',
+  '\uFB05': '\u017F\u0074',
+  '\uFB06': '\u0073\u0074',
+  '\uFB13': '\u0574\u0576',
+  '\uFB14': '\u0574\u0565',
+  '\uFB15': '\u0574\u056B',
+  '\uFB16': '\u057E\u0576',
+  '\uFB17': '\u0574\u056D',
+  '\uFB4F': '\u05D0\u05DC',
+  '\uFE49': '\u203E',
+  '\uFE4A': '\u203E',
+  '\uFE4B': '\u203E',
+  '\uFE4C': '\u203E',
+  '\uFE4D': '\u005F',
+  '\uFE4E': '\u005F',
+  '\uFE4F': '\u005F'
+};
+
+function fontCharsToUnicode(charCodes, fontProperties) {
+  var toUnicode = fontProperties.toUnicode;
+  var composite = fontProperties.composite;
+  var encoding, differences, cidToUnicode;
+  var result = '';
+  if (composite) {
+    cidToUnicode = fontProperties.cidToUnicode;
+    for (var i = 0, ii = charCodes.length; i < ii; i += 2) {
+      var charCode = (charCodes.charCodeAt(i) << 8) |
+        charCodes.charCodeAt(i + 1);
+      if (toUnicode && charCode in toUnicode) {
+        var unicode = toUnicode[charCode];
+        result += typeof unicode !== 'number' ? unicode :
+          String.fromCharCode(unicode);
+        continue;
+      }
+      result += String.fromCharCode(!cidToUnicode ? charCode :
+        cidToUnicode[charCode] || charCode);
+    }
+  } else {
+    differences = fontProperties.differences;
+    encoding = fontProperties.baseEncoding;
+    for (var i = 0, ii = charCodes.length; i < ii; i++) {
+      var charCode = charCodes.charCodeAt(i);
+      var unicode;
+      if (toUnicode && charCode in toUnicode) {
+        var unicode = toUnicode[charCode];
+        result += typeof unicode !== 'number' ? unicode :
+          String.fromCharCode(unicode);
+        continue;
+      }
+
+      var glyphName = charCode in differences ? differences[charCode] :
+        encoding[charCode];
+      if (glyphName in GlyphsUnicode) {
+        result += String.fromCharCode(GlyphsUnicode[glyphName]);
+        continue;
+      }
+      result += String.fromCharCode(charCode);
+    }
+  }
+  // normalizing the unicode characters
+  for (var i = 0, ii = result.length; i < ii; i++) {
+    if (!(result[i] in NormalizedUnicodes))
+      continue;
+    result = result.substring(0, i) + NormalizedUnicodes[result[i]] +
+      result.substring(i + 1);
+    ii = result.length;
+  }
+  return result;
+}
+
 /**
  * 'Font' is the class the outside world should use, it encapsulate all the font
  * decoding logics whatever type it is (assuming the font type is supported).
@@ -2477,6 +3207,7 @@ var Font = (function FontClosure() {
           }
 
           // MacRoman encoding address by re-encoding the cmap table
+
           fontCharCode = glyphName in this.glyphNameMap ?
             this.glyphNameMap[glyphName] : GlyphsUnicode[glyphName];
           break;
diff --git a/src/worker.js b/src/worker.js
index 25f3f52cd..b3ba7671e 100644
--- a/src/worker.js
+++ b/src/worker.js
@@ -123,7 +123,6 @@ var WorkerMessageHandler = {
     handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
       var pageNum = data.pageIndex + 1;
 
-
       // The following code does quite the same as
       // Page.prototype.startRendering, but stops at one point and sends the
       // result back to the main thread.
@@ -183,6 +182,24 @@ var WorkerMessageHandler = {
         depFonts: Object.keys(fonts)
       });
     }, this);
+
+    handler.on('GetTextContent', function wphExtractText(data, promise) {
+      var pageNum = data.pageIndex + 1;
+      var start = Date.now();
+
+      var textContent = '';
+      try {
+        var page = pdfModel.getPage(pageNum);
+        textContent = page.extractTextContent();
+        promise.resolve(textContent);
+      } catch (e) {
+        // Skip errored pages
+        promise.reject(e);
+      }
+
+      console.log('text indexing: page=%d - time=%dms',
+                      pageNum, Date.now() - start);
+    });
   }
 };
 
diff --git a/web/images/edit-find.svg b/web/images/edit-find.svg
new file mode 100644
index 000000000..a499b486c
--- /dev/null
+++ b/web/images/edit-find.svg
@@ -0,0 +1,750 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="90.000000"
+   inkscape:export-xdpi="90.000000"
+   inkscape:export-filename="/home/steven/edit-find-48.png"
+   sodipodi:docname="edit-find.svg"
+   sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+   inkscape:version="0.46"
+   sodipodi:version="0.32"
+   id="svg249"
+   height="48.000000px"
+   width="48.000000px"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs3">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 24 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="48 : 24 : 1"
+       inkscape:persp3d-origin="24 : 16 : 1"
+       id="perspective113" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient5031"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5060">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop5062" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5064" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient5029"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop5050" />
+      <stop
+         id="stop5056"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5052" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048"
+       id="linearGradient5027"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4542">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop4544" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop4546" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient15662">
+      <stop
+         id="stop15664"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop15666"
+         offset="1.0000000"
+         style="stop-color:#f8f8f8;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       id="aigrd3"
+       cx="20.8921"
+       cy="64.5679"
+       r="5.257"
+       fx="20.8921"
+       fy="64.5679"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         offset="0"
+         style="stop-color:#F0F0F0"
+         id="stop15573" />
+      <stop
+         offset="1.0000000"
+         style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+         id="stop15575" />
+    </radialGradient>
+    <radialGradient
+       id="aigrd2"
+       cx="20.8921"
+       cy="114.5684"
+       r="5.256"
+       fx="20.8921"
+       fy="114.5684"
+       gradientUnits="userSpaceOnUse">
+      <stop
+         offset="0"
+         style="stop-color:#F0F0F0"
+         id="stop15566" />
+      <stop
+         offset="1.0000000"
+         style="stop-color:#9a9a9a;stop-opacity:1.0000000;"
+         id="stop15568" />
+    </radialGradient>
+    <linearGradient
+       id="linearGradient269">
+      <stop
+         id="stop270"
+         offset="0.0000000"
+         style="stop-color:#a3a3a3;stop-opacity:1.0000000;" />
+      <stop
+         id="stop271"
+         offset="1.0000000"
+         style="stop-color:#4c4c4c;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient259">
+      <stop
+         id="stop260"
+         offset="0.0000000"
+         style="stop-color:#fafafa;stop-opacity:1.0000000;" />
+      <stop
+         id="stop261"
+         offset="1.0000000"
+         style="stop-color:#bbbbbb;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient269"
+       id="radialGradient15656"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.968273,0.000000,0.000000,1.032767,3.353553,0.646447)"
+       cx="8.8244190"
+       cy="3.7561285"
+       fx="8.8244190"
+       fy="3.7561285"
+       r="37.751713" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient259"
+       id="radialGradient15658"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(0.960493,1.041132)"
+       cx="33.966679"
+       cy="35.736916"
+       fx="33.966679"
+       fy="35.736916"
+       r="86.708450" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient15662"
+       id="radialGradient15668"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.968273,0.000000,0.000000,1.032767,3.353553,0.646447)"
+       cx="8.1435566"
+       cy="7.2678967"
+       fx="8.1435566"
+       fy="7.2678967"
+       r="38.158695" />
+    <radialGradient
+       r="5.256"
+       fy="114.5684"
+       fx="20.8921"
+       cy="114.5684"
+       cx="20.8921"
+       gradientTransform="matrix(0.229703,0.000000,0.000000,0.229703,4.613529,3.979808)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2283"
+       xlink:href="#aigrd2"
+       inkscape:collect="always" />
+    <radialGradient
+       r="5.257"
+       fy="64.5679"
+       fx="20.8921"
+       cy="64.5679"
+       cx="20.8921"
+       gradientTransform="matrix(0.229703,0.000000,0.000000,0.229703,4.613529,3.979808)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient2285"
+       xlink:href="#aigrd3"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4542"
+       id="radialGradient4548"
+       cx="24.306795"
+       cy="42.07798"
+       fx="24.306795"
+       fy="42.07798"
+       r="15.821514"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.284916,0.000000,30.08928)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       id="linearGradient4440">
+      <stop
+         id="stop4442"
+         offset="0"
+         style="stop-color:#7d7d7d;stop-opacity:1;" />
+      <stop
+         style="stop-color:#b1b1b1;stop-opacity:1.0000000;"
+         offset="0.50000000"
+         id="stop4448" />
+      <stop
+         id="stop4444"
+         offset="1.0000000"
+         style="stop-color:#686868;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4454">
+      <stop
+         id="stop4456"
+         offset="0.0000000"
+         style="stop-color:#729fcf;stop-opacity:0.20784314;" />
+      <stop
+         id="stop4458"
+         offset="1.0000000"
+         style="stop-color:#729fcf;stop-opacity:0.67619050;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4467">
+      <stop
+         id="stop4469"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4471"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.24761905;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4477"
+       inkscape:collect="always">
+      <stop
+         id="stop4479"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop4481"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2366">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop2368" />
+      <stop
+         id="stop2374"
+         offset="0.50000000"
+         style="stop-color:#ffffff;stop-opacity:0.21904762;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2370" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2846">
+      <stop
+         style="stop-color:#8a8a8a;stop-opacity:1.0000000;"
+         offset="0.0000000"
+         id="stop2848" />
+      <stop
+         style="stop-color:#484848;stop-opacity:1.0000000;"
+         offset="1.0000000"
+         id="stop2850" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4477"
+       id="radialGradient1527"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.237968,-8.821068e-16,28.93278)"
+       cx="24.130018"
+       cy="37.967922"
+       fx="24.130018"
+       fy="37.967922"
+       r="16.528622" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2846"
+       id="linearGradient1529"
+       gradientUnits="userSpaceOnUse"
+       x1="27.366341"
+       y1="26.580296"
+       x2="31.335964"
+       y2="30.557772" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4440"
+       id="linearGradient1531"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.334593,0.000000,0.000000,1.291292,-6.973842,-7.460658)"
+       x1="30.656250"
+       y1="34.000000"
+       x2="33.218750"
+       y2="31.062500" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2366"
+       id="linearGradient1533"
+       gradientUnits="userSpaceOnUse"
+       x1="18.292673"
+       y1="13.602121"
+       x2="17.500893"
+       y2="25.743469" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4454"
+       id="radialGradient1537"
+       gradientUnits="userSpaceOnUse"
+       cx="18.240929"
+       cy="21.817987"
+       fx="18.240929"
+       fy="21.817987"
+       r="8.3085051" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4467"
+       id="radialGradient1539"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.592963,-7.746900e-24,-5.714443e-24,2.252104,-25.05975,-18.94100)"
+       cx="15.414371"
+       cy="13.078408"
+       fx="15.414371"
+       fy="13.078408"
+       r="6.6562500" />
+  </defs>
+  <sodipodi:namedview
+     inkscape:window-y="30"
+     inkscape:window-x="418"
+     inkscape:window-height="818"
+     inkscape:window-width="1016"
+     inkscape:document-units="px"
+     inkscape:grid-bbox="true"
+     showgrid="true"
+     inkscape:current-layer="layer6"
+     inkscape:cy="14.980943"
+     inkscape:cx="25.938708"
+     inkscape:zoom="1"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="0.25490196"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     inkscape:showpageshadow="false" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Edit Find</dc:title>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>edit</rdf:li>
+            <rdf:li>find</rdf:li>
+            <rdf:li>locate</rdf:li>
+            <rdf:li>search</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Steven Garrity</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source />
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer6"
+     inkscape:label="Shadow">
+    <g
+       style="display:inline"
+       id="g5022"
+       transform="matrix(2.165152e-2,0,0,1.485743e-2,43.0076,42.68539)">
+      <rect
+         y="-150.69685"
+         x="-1559.2523"
+         height="478.35718"
+         width="1339.6335"
+         id="rect4173"
+         style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+      <path
+         sodipodi:nodetypes="cccc"
+         id="path5058"
+         d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+      <path
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+         id="path5018"
+         sodipodi:nodetypes="cccc" />
+    </g>
+  </g>
+  <g
+     style="display:inline"
+     inkscape:groupmode="layer"
+     inkscape:label="Base"
+     id="layer1">
+    <rect
+       style="color:#000000;fill:url(#radialGradient15658);fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15656);stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+       id="rect15391"
+       width="34.875000"
+       height="40.920494"
+       x="6.6035528"
+       y="3.6464462"
+       ry="1.1490486" />
+    <rect
+       style="color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient15668);stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+       id="rect15660"
+       width="32.775887"
+       height="38.946384"
+       x="7.6660538"
+       y="4.5839462"
+       ry="0.14904857"
+       rx="0.14904857" />
+    <g
+       transform="translate(0.646447,-3.798933e-2)"
+       id="g2270">
+      <g
+         id="g1440"
+         style="fill:#ffffff;fill-opacity:1.0000000;fill-rule:nonzero;stroke:#000000;stroke-miterlimit:4.0000000"
+         transform="matrix(0.229703,0.000000,0.000000,0.229703,4.967081,4.244972)">
+        <radialGradient
+           id="radialGradient1442"
+           cx="20.892099"
+           cy="114.56840"
+           r="5.2560000"
+           fx="20.892099"
+           fy="114.56840"
+           gradientUnits="userSpaceOnUse">
+          <stop
+             offset="0"
+             style="stop-color:#F0F0F0"
+             id="stop1444" />
+          <stop
+             offset="1"
+             style="stop-color:#474747"
+             id="stop1446" />
+        </radialGradient>
+        <path
+           style="stroke:none"
+           d="M 23.428000,113.07000 C 23.428000,115.04300 21.828000,116.64200 19.855000,116.64200 C 17.881000,116.64200 16.282000,115.04200 16.282000,113.07000 C 16.282000,111.09600 17.882000,109.49700 19.855000,109.49700 C 21.828000,109.49700 23.428000,111.09700 23.428000,113.07000 z "
+           id="path1448" />
+        <radialGradient
+           id="radialGradient1450"
+           cx="20.892099"
+           cy="64.567902"
+           r="5.2570000"
+           fx="20.892099"
+           fy="64.567902"
+           gradientUnits="userSpaceOnUse">
+          <stop
+             offset="0"
+             style="stop-color:#F0F0F0"
+             id="stop1452" />
+          <stop
+             offset="1"
+             style="stop-color:#474747"
+             id="stop1454" />
+        </radialGradient>
+        <path
+           style="stroke:none"
+           d="M 23.428000,63.070000 C 23.428000,65.043000 21.828000,66.643000 19.855000,66.643000 C 17.881000,66.643000 16.282000,65.043000 16.282000,63.070000 C 16.282000,61.096000 17.882000,59.497000 19.855000,59.497000 C 21.828000,59.497000 23.428000,61.097000 23.428000,63.070000 z "
+           id="path1456" />
+      </g>
+      <path
+         style="fill:url(#radialGradient2283);fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+         d="M 9.9950109,29.952326 C 9.9950109,30.405530 9.6274861,30.772825 9.1742821,30.772825 C 8.7208483,30.772825 8.3535532,30.405301 8.3535532,29.952326 C 8.3535532,29.498892 8.7210780,29.131597 9.1742821,29.131597 C 9.6274861,29.131597 9.9950109,29.499122 9.9950109,29.952326 z "
+         id="path15570" />
+      <path
+         style="fill:url(#radialGradient2285);fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+         d="M 9.9950109,18.467176 C 9.9950109,18.920380 9.6274861,19.287905 9.1742821,19.287905 C 8.7208483,19.287905 8.3535532,18.920380 8.3535532,18.467176 C 8.3535532,18.013742 8.7210780,17.646447 9.1742821,17.646447 C 9.6274861,17.646447 9.9950109,18.013972 9.9950109,18.467176 z "
+         id="path15577" />
+    </g>
+    <path
+       style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.98855311;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.017543854"
+       d="M 11.505723,5.4942766 L 11.505723,43.400869"
+       id="path15672"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:0.20467831"
+       d="M 12.500000,5.0205154 L 12.500000,43.038228"
+       id="path15674"
+       sodipodi:nodetypes="cc" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer5"
+     inkscape:label="Magnifying Glass"
+     style="display:inline">
+    <g
+       transform="matrix(0.909091,0.000000,0.000000,1.000000,2.363628,0.000000)"
+       id="g2253">
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15686"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="9.0000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15688"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="11.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15690"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="13.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15692"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="15.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15694"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="17.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15696"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="19.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15698"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="21.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15700"
+         width="22.000004"
+         height="1.0000000"
+         x="15.000002"
+         y="23.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15732"
+         width="9.9000053"
+         height="1.0000000"
+         x="14.999992"
+         y="25.000000"
+         rx="0.068204239"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15736"
+         width="22.000004"
+         height="1.0000000"
+         x="14.999992"
+         y="29.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15738"
+         width="22.000004"
+         height="1.0000000"
+         x="14.999992"
+         y="31.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15740"
+         width="22.000004"
+         height="1.0000000"
+         x="14.999992"
+         y="33.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15742"
+         width="22.000004"
+         height="1.0000000"
+         x="14.999992"
+         y="35.000000"
+         rx="0.15156493"
+         ry="0.065390877" />
+      <rect
+         style="color:#000000;fill:#9b9b9b;fill-opacity:0.54970759;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.081871338;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         id="rect15744"
+         width="15.400014"
+         height="1.0000000"
+         x="14.999992"
+         y="37.000000"
+         rx="0.10609552"
+         ry="0.065390877" />
+    </g>
+    <g
+       id="g1772"
+       transform="matrix(0.665377,0.000000,0.000000,0.665377,15.98645,17.90835)">
+      <path
+         sodipodi:type="arc"
+         style="opacity:0.17112298;color:#000000;fill:url(#radialGradient1527);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         id="path4475"
+         sodipodi:cx="24.130018"
+         sodipodi:cy="37.967922"
+         sodipodi:rx="16.528622"
+         sodipodi:ry="3.9332814"
+         d="M 40.658640 37.967922 A 16.528622 3.9332814 0 1 1  7.6013966,37.967922 A 16.528622 3.9332814 0 1 1  40.658640 37.967922 z"
+         transform="matrix(1.446431,0.000000,0.000000,1.519990,-10.97453,-17.75168)" />
+      <path
+         sodipodi:nodetypes="csscccscccscczzzz"
+         id="path2844"
+         d="M 18.627569,3.1435548 C 10.488439,3.1435548 3.8827682,9.7492259 3.8827682,17.888356 C 3.8827682,26.027486 10.488439,32.633158 18.627569,32.633158 C 22.107124,32.633158 25.178570,31.248765 27.701292,29.230511 C 27.495915,30.237392 27.623257,31.265879 28.457436,31.990436 L 39.421520,41.517846 C 40.654936,42.589175 42.508982,42.448806 43.580310,41.215389 C 44.651638,39.981971 44.511269,38.127927 43.277853,37.056599 L 32.313769,27.529188 C 31.642242,26.945909 30.820891,26.773219 30.007531,26.886466 C 31.994231,24.374044 33.372370,21.337663 33.372370,17.888356 C 33.372370,9.7492259 26.766699,3.1435548 18.627569,3.1435548 z M 18.551954,4.3697381 C 26.191413,4.3697381 31.843729,9.1586886 31.843729,17.661513 C 31.843729,26.336626 26.027039,30.953288 18.551954,30.953288 C 11.249005,30.953288 5.2601806,25.475196 5.2601806,17.661513 C 5.2601806,9.6774061 11.084819,4.3697380 18.551954,4.3697381 z "
+         style="opacity:1.0000000;color:#000000;fill:#dcdcdc;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient1529);stroke-width:3.0058157;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
+      <path
+         style="opacity:1.0000000;color:#000000;fill:#dcdcdc;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000004;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         d="M 18.602905,3.0803551 C 10.437465,3.0803551 3.8104408,9.7073791 3.8104408,17.872819 C 3.8104408,26.038259 10.437465,32.665283 18.602905,32.665283 C 22.093708,32.665283 25.175082,31.276416 27.705960,29.251638 C 27.499919,30.261774 27.627672,31.293585 28.464547,32.020484 L 39.464073,41.578691 C 40.701476,42.653483 42.561515,42.512661 43.636306,41.275256 C 44.711097,40.037852 44.570274,38.177814 43.332871,37.103023 L 32.333346,27.544815 C 31.659648,26.959651 30.835642,26.786402 30.019653,26.900016 C 32.012775,24.379472 33.395369,21.333276 33.395369,17.872819 C 33.395369,9.7073791 26.768345,3.0803551 18.602905,3.0803551 z M 18.527046,6.2664243 C 24.808154,6.2664245 29.905864,11.364135 29.905864,17.645243 C 29.905864,23.926351 24.808154,29.024061 18.527046,29.024061 C 12.245938,29.024061 7.1482276,23.926351 7.1482276,17.645243 C 7.1482278,11.364135 12.245938,6.2664243 18.527046,6.2664243 z "
+         id="path4430" />
+      <path
+         style="opacity:1.0000000;color:#000000;fill:url(#linearGradient1531);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         d="M 39.507004,41.577690 C 39.028332,39.304503 40.904334,36.766268 43.091057,36.789315 C 43.091057,36.789315 32.330690,27.531204 32.330690,27.531204 C 29.385899,27.474498 28.061188,29.803820 28.553876,32.131126 L 39.507004,41.577690 z "
+         id="path4438"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         sodipodi:type="arc"
+         style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient1533);stroke-width:1.2064340;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         id="path4450"
+         sodipodi:cx="17.500893"
+         sodipodi:cy="18.920233"
+         sodipodi:rx="11.048544"
+         sodipodi:ry="11.048544"
+         d="M 28.549437 18.920233 A 11.048544 11.048544 0 1 1  6.4523487,18.920233 A 11.048544 11.048544 0 1 1  28.549437 18.920233 z"
+         transform="matrix(1.245743,0.000000,0.000000,1.245743,-3.425346,-6.177033)" />
+      <rect
+         style="opacity:0.43315509;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.5029539;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         id="rect4495"
+         width="19.048439"
+         height="4.4404783"
+         x="40.373337"
+         y="0.14086054"
+         rx="3.2112026"
+         ry="2.8373930"
+         transform="matrix(0.752986,0.658037,-0.648902,0.760872,0.000000,0.000000)" />
+      <path
+         sodipodi:type="arc"
+         style="color:#000000;fill:url(#radialGradient1537);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#3063a3;stroke-width:1.0745695;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible"
+         id="path4452"
+         sodipodi:cx="17.589281"
+         sodipodi:cy="18.478292"
+         sodipodi:rx="8.3085051"
+         sodipodi:ry="8.3085051"
+         d="M 25.897786 18.478292 A 8.3085051 8.3085051 0 1 1  9.2807760,18.478292 A 8.3085051 8.3085051 0 1 1  25.897786 18.478292 z"
+         transform="matrix(1.398614,0.000000,0.000000,1.398614,-6.224338,-8.298958)" />
+      <path
+         style="opacity:0.83422458;color:#000000;fill:url(#radialGradient1539);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         d="M 18.156915,7.3966938 C 12.949325,7.3966938 8.7323681,11.613651 8.7323681,16.821241 C 8.7323681,18.325216 9.1526753,19.709014 9.7795400,20.971144 C 11.031920,21.432757 12.362297,21.746827 13.774307,21.746827 C 19.945262,21.746827 24.873589,16.885190 25.254413,10.809698 C 23.523449,8.7641668 21.044374,7.3966938 18.156915,7.3966938 z "
+         id="path4462" />
+    </g>
+  </g>
+</svg>
diff --git a/web/viewer.css b/web/viewer.css
index 9a0cf388c..d042feab7 100644
--- a/web/viewer.css
+++ b/web/viewer.css
@@ -186,9 +186,47 @@ body {
   box-shadow: 0px 2px 10px #ff0;
 }
 
+#searchScrollView {
+  position: absolute;
+  top: 10px;
+  bottom: 10px;
+  left: 10px;
+  width: 280px;
+}
+
+#searchToolbar {
+  padding-left: 0px;
+  right: 0px;
+  padding-top: 0px;
+  padding-bottom: 5px;
+}
+
+#searchToolbar > input {
+  width: 220px;
+}
+
+#searchResults {
+  overflow: auto;
+  background-color: #fff;
+  position: absolute;
+  top: 30px;
+  bottom: 0px;
+  left: 0px;
+  right: 0;
+  font-size: smaller;
+  opacity: 0.7;
+}
+
+#searchResults a {
+  display: block;
+  white-space: pre;
+  text-decoration: none;
+  color: black;
+}
+
 #sidebarControls {
   position:absolute;
-  width: 120px;
+  width: 180px;
   height: 32px;
   left: 15px;
   bottom: 35px;
diff --git a/web/viewer.html b/web/viewer.html
index ef61ce697..07817a885 100644
--- a/web/viewer.html
+++ b/web/viewer.html
@@ -133,6 +133,13 @@
         <div id="outlineScrollView" hidden='true'>
           <div id="outlineView"></div>
         </div>
+        <div id="searchScrollView" hidden='true'>
+          <div id="searchToolbar">
+            <input id="searchTermsInput" onkeydown='if (event.keyCode == 13) PDFView.search()'>
+            <button id="searchButton" onclick='PDFView.search()'>Find</button>
+          </div>
+          <div id="searchResults"></div>
+        </div>
         <div id="sidebarControls">
           <button id="thumbsSwitch" title="Show Thumbnails" onclick="PDFView.switchSidebarView('thumbs')" data-selected>
             <img src="images/nav-thumbs.svg" align="top" height="16" alt="Thumbs" />
@@ -140,6 +147,9 @@
           <button id="outlineSwitch" title="Show Document Outline" onclick="PDFView.switchSidebarView('outline')" disabled>
             <img src="images/nav-outline.svg" align="top" height="16" alt="Document Outline" />
           </button>
+          <button id="searchSwitch" title="Show Search" onclick="PDFView.switchSidebarView('search')">
+            <img src="images/edit-find.svg" align="top" height="16" alt="Search Document" />
+          </button>
         </div>
       </div>
     </div>
diff --git a/web/viewer.js b/web/viewer.js
index 340cf2005..054c08fc1 100644
--- a/web/viewer.js
+++ b/web/viewer.js
@@ -214,6 +214,8 @@ var PDFView = {
   currentScale: kUnknownScale,
   currentScaleValue: null,
   initialBookmark: document.location.hash.substring(1),
+  startedTextExtraction: false,
+  pageText: [],
 
   setScale: function pdfViewSetScale(val, resetAutoSettings) {
     if (val == this.currentScale)
@@ -592,6 +594,67 @@ var PDFView = {
     }
   },
 
+  search: function pdfViewStartSearch() {
+    // Limit this function to run every <SEARCH_TIMEOUT>ms.
+    var SEARCH_TIMEOUT = 250;
+    var lastSeach = this.lastSearch;
+    var now = Date.now();
+    if (lastSeach && (now - lastSeach) < SEARCH_TIMEOUT) {
+      if (!this.searchTimer) {
+        this.searchTimer = setTimeout(function resumeSearch() {
+            PDFView.search();
+          },
+          SEARCH_TIMEOUT - (now - lastSeach)
+        );
+      }
+      return;
+    }
+    this.searchTimer = null;
+    this.lastSearch = now;
+
+    function bindLink(link, pageNumber) {
+      link.href = '#' + pageNumber;
+      link.onclick = function searchBindLink() {
+        PDFView.page = pageNumber;
+        return false;
+      };
+    }
+
+    var searchResults = document.getElementById('searchResults');
+
+    var searchTermsInput = document.getElementById('searchTermsInput');
+    searchResults.removeAttribute('hidden');
+    searchResults.textContent = '';
+
+    var terms = searchTermsInput.value;
+
+    if (!terms)
+      return;
+
+    // simple search: removing spaces and hyphens, then scanning every
+    terms = terms.replace(/\s-/g, '').toLowerCase();
+    var index = PDFView.pageText;
+    var pageFound = false;
+    for (var i = 0, ii = index.length; i < ii; i++) {
+      var pageText = index[i].replace(/\s-/g, '').toLowerCase();
+      var j = pageText.indexOf(terms);
+      if (j < 0)
+        continue;
+
+      var pageNumber = i + 1;
+      var textSample = index[i].substr(j, 50);
+      var link = document.createElement('a');
+      bindLink(link, pageNumber);
+      link.textContent = 'Page ' + pageNumber + ': ' + textSample;
+      searchResults.appendChild(link);
+
+      pageFound = true;
+    }
+    if (!pageFound) {
+      searchResults.textContent = '(Not found)';
+    }
+  },
+
   setHash: function pdfViewSetHash(hash) {
     if (!hash)
       return;
@@ -633,24 +696,58 @@ var PDFView = {
 
   switchSidebarView: function pdfViewSwitchSidebarView(view) {
     var thumbsScrollView = document.getElementById('sidebarScrollView');
-    var outlineScrollView = document.getElementById('outlineScrollView');
     var thumbsSwitchButton = document.getElementById('thumbsSwitch');
-    var outlineSwitchButton = document.getElementById('outlineSwitch');
-    switch (view) {
-      case 'thumbs':
-        thumbsScrollView.removeAttribute('hidden');
-        outlineScrollView.setAttribute('hidden', 'true');
-        thumbsSwitchButton.setAttribute('data-selected', true);
-        outlineSwitchButton.removeAttribute('data-selected');
-        updateThumbViewArea();
-        break;
-      case 'outline':
-        thumbsScrollView.setAttribute('hidden', 'true');
-        outlineScrollView.removeAttribute('hidden');
-        thumbsSwitchButton.removeAttribute('data-selected');
-        outlineSwitchButton.setAttribute('data-selected', true);
-        break;
+    if (view == 'thumbs') {
+      thumbsScrollView.removeAttribute('hidden');
+      thumbsSwitchButton.setAttribute('data-selected', true);
+    } else {
+      thumbsScrollView.setAttribute('hidden', 'true');
+      thumbsSwitchButton.removeAttribute('data-selected');
     }
+
+    var outlineScrollView = document.getElementById('outlineScrollView');
+    var outlineSwitchButton = document.getElementById('outlineSwitch');
+    if (view == 'outline') {
+      outlineScrollView.removeAttribute('hidden');
+      outlineSwitchButton.setAttribute('data-selected', true);
+    } else {
+      outlineScrollView.setAttribute('hidden', 'true');
+      outlineSwitchButton.removeAttribute('data-selected');
+    }
+
+    var searchScrollView = document.getElementById('searchScrollView');
+    var searchSwitchButton = document.getElementById('searchSwitch');
+    if (view == 'search') {
+      searchScrollView.removeAttribute('hidden');
+      searchSwitchButton.setAttribute('data-selected', true);
+
+      var searchTermsInput = document.getElementById('searchTermsInput');
+      searchTermsInput.focus();
+
+      // Start text extraction as soon as the search gets displayed.
+      this.extractText();
+    } else {
+      searchScrollView.setAttribute('hidden', 'true');
+      searchSwitchButton.removeAttribute('data-selected');
+    }
+  },
+
+  extractText: function() {
+    if (this.startedTextExtraction)
+      return;
+    this.startedTextExtraction = true;
+    var self = this;
+    function extractPageText(pageIndex) {
+      self.pages[pageIndex].pdfPage.getTextContent().then(
+        function textContentResolved(textContent) {
+          self.pageText[pageIndex] = textContent;
+          self.search();
+          if ((pageIndex + 1) < self.pages.length)
+            extractPageText(pageIndex + 1);
+        }
+      );
+    };
+    extractPageText(0);
   },
 
   pinSidebar: function pdfViewPinSidebar() {