[poppler] poppler/poppler: CairoOutputDev.cc, 1.16, 1.17 CairoOutputDev.h, 1.6, 1.7 Page.cc, 1.4, 1.5 Page.h, 1.3, 1.4 TextOutputDev.cc, 1.1.1.1, 1.2 TextOutputDev.h, 1.2, 1.3

Kristian Hogsberg krh at freedesktop.org
Wed Jun 29 14:24:59 PDT 2005


Update of /cvs/poppler/poppler/poppler
In directory gabe:/tmp/cvs-serv13816/poppler

Modified Files:
	CairoOutputDev.cc CairoOutputDev.h Page.cc Page.h 
	TextOutputDev.cc TextOutputDev.h 
Log Message:
2005-06-29  Kristian Høgsberg  <krh at redhat.com>

        * configure.ac:
        * glib/poppler-page.cc:
        * glib/poppler-page.h:
        * glib/poppler-private.h:
        * poppler/CairoOutputDev.cc:
        * poppler/CairoOutputDev.h:
        * poppler/Page.cc:
        * poppler/Page.h:
        * poppler/TextOutputDev.cc:
        * poppler/TextOutputDev.h: Add support for rendering real
        selection (based on text flow).



Index: CairoOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CairoOutputDev.cc,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- CairoOutputDev.cc	28 Jun 2005 03:44:12 -0000	1.16
+++ CairoOutputDev.cc	29 Jun 2005 21:24:57 -0000	1.17
@@ -53,6 +53,7 @@
 
   FT_Init_FreeType(&ft_lib);
   fontEngine = NULL;
+  glyphs = NULL;
   surface = NULL;
 }
 
@@ -219,7 +220,6 @@
 
   LOG(printf ("updateFont() font=%s\n", state->getFont()->getName()->getCString()));
   
-  /* Needs to be rethough, since fonts are now handled by cairo */
   needFontUpdate = gFalse;
 
   currentFont = fontEngine->getFont (state->getFont(), xref);
@@ -342,6 +342,9 @@
 {
   int len = s->getLength();
 
+  if (needFontUpdate)
+    updateFont(state);
+
   glyphs = (cairo_glyph_t *) gmalloc (len * sizeof (cairo_glyph_t));
   glyphCount = 0;
 }
@@ -364,8 +367,6 @@
 {
   int render;
 
-  if (needFontUpdate)
-    updateFont(state);
   if (!currentFont)
     return;
    
@@ -375,8 +376,11 @@
     return;
 
   // ignore empty strings
-  if (glyphCount == 0)
+  if (glyphCount == 0) {
+    gfree(glyphs);
+    glyphs = NULL;
     return;
+  }
   
   if (!(render & 1)) {
     LOG (printf ("fill string\n"));
@@ -405,6 +409,7 @@
   }
   
   gfree (glyphs);
+  glyphs = NULL;
 }
 
 GBool CairoOutputDev::beginType3Char(GfxState *state, double x, double y,

Index: CairoOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/CairoOutputDev.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- CairoOutputDev.h	28 Jun 2005 03:44:12 -0000	1.6
+++ CairoOutputDev.h	29 Jun 2005 21:24:57 -0000	1.7
@@ -146,7 +146,7 @@
   FT_Library ft_lib;
   CairoFontEngine *fontEngine;
   cairo_t *cairo;
-  GBool needFontUpdate;		// set when the font needs to be updated
+  GBool needFontUpdate;                // set when the font needs to be updated
   cairo_surface_t *surface;
   cairo_glyph_t *glyphs;
   int glyphCount;

Index: Page.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Page.cc,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Page.cc	21 Apr 2005 05:20:25 -0000	1.4
+++ Page.cc	29 Jun 2005 21:24:57 -0000	1.5
@@ -25,6 +25,7 @@
 #include "Gfx.h"
 #include "GfxState.h"
 #include "Annot.h"
+#include "TextOutputDev.h"
 #endif
 #include "Error.h"
 #include "Page.h"
@@ -250,23 +251,18 @@
                annotDisplayDecideCbk, annotDisplayDecideCbkData);
 }
 
-void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
-			int rotate, GBool crop,
-			int sliceX, int sliceY, int sliceW, int sliceH,
-			Links *links, Catalog *catalog,
-			GBool (*abortCheckCbk)(void *data),
-			void *abortCheckCbkData,
-                        GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
-                        void *annotDisplayDecideCbkData) {
-#ifndef PDF_PARSER_ONLY
+Gfx *Page::createGfx(OutputDev *out, double hDPI, double vDPI,
+		     int rotate, GBool crop,
+		     int sliceX, int sliceY, int sliceW, int sliceH,
+		     Links *links, Catalog *catalog,
+		     GBool (*abortCheckCbk)(void *data),
+		     void *abortCheckCbkData,
+		     GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
+		     void *annotDisplayDecideCbkData) {
   PDFRectangle *mediaBox, *cropBox;
   PDFRectangle box;
   Gfx *gfx;
-  Object obj;
-  Link *link;
-  Annots *annotList;
   double kx, ky;
-  int i;
 
   rotate += getRotate();
   if (rotate >= 360) {
@@ -338,6 +334,30 @@
   gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
 		hDPI, vDPI, &box, crop && isCropped(), cropBox, rotate,
 		abortCheckCbk, abortCheckCbkData);
+
+  return gfx;
+}
+
+void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
+			int rotate, GBool crop,
+			int sliceX, int sliceY, int sliceW, int sliceH,
+			Links *links, Catalog *catalog,
+			GBool (*abortCheckCbk)(void *data),
+			void *abortCheckCbkData,
+                        GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
+                        void *annotDisplayDecideCbkData) {
+  Gfx *gfx;
+  Object obj;
+  Link *link;
+  Annots *annotList;
+  int i;
+
+  gfx = createGfx(out, hDPI, vDPI, rotate, crop,
+		  sliceX, sliceY, sliceW, sliceH,
+		  links, catalog,
+		  abortCheckCbk, abortCheckCbkData,
+		  annotDisplayDecideCbk, annotDisplayDecideCbkData);
+
   contents.fetch(xref, &obj);
   if (!obj.isNull()) {
     gfx->saveState();
@@ -378,7 +398,18 @@
   delete annotList;
 
   delete gfx;
-#endif
+}
+
+void Page::display(Gfx *gfx) {
+  Object obj;
+
+  contents.fetch(xref, &obj);
+  if (!obj.isNull()) {
+    gfx->saveState();
+    gfx->display(&obj);
+    gfx->restoreState();
+  }
+  obj.free();
 }
 
 GBool Page::loadThumb(unsigned char **data_out,

Index: Page.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/Page.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- Page.h	2 Apr 2005 22:16:38 -0000	1.3
+++ Page.h	29 Jun 2005 21:24:57 -0000	1.4
@@ -22,6 +22,7 @@
 class Catalog;
 class Annots;
 class Annot;
+class Gfx;
 
 //------------------------------------------------------------------------
 
@@ -147,6 +148,15 @@
   // Get transition.
   Object *getTrans(Object *obj) { return trans.fetch(xref, obj); }
 
+  Gfx *createGfx(OutputDev *out, double hDPI, double vDPI,
+		 int rotate, GBool crop,
+		 int sliceX, int sliceY, int sliceW, int sliceH,
+		 Links *links, Catalog *catalog,
+		 GBool (*abortCheckCbk)(void *data),
+		 void *abortCheckCbkData,
+		 GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
+		 void *annotDisplayDecideCbkData);
+
   // Display a page.
   void display(OutputDev *out, double hDPI, double vDPI,
 	       int rotate, GBool crop,
@@ -166,6 +176,8 @@
                     GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
                     void *annotDisplayDecideCbkData = NULL);
 
+  void display(Gfx *gfx);
+
 private:
 
   XRef *xref;			// the xref table for this PDF file

Index: TextOutputDev.cc
===================================================================
RCS file: /cvs/poppler/poppler/poppler/TextOutputDev.cc,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- TextOutputDev.cc	3 Mar 2005 19:46:04 -0000	1.1.1.1
+++ TextOutputDev.cc	29 Jun 2005 21:24:57 -0000	1.2
@@ -31,6 +31,7 @@
 #include "UnicodeTypeTable.h"
 #include "GfxState.h"
 #include "TextOutputDev.h"
+#include "Page.h"
 
 #ifdef MACOS
 // needed for setting type/creator of MacOS files
@@ -208,6 +209,7 @@
     break;
   }
   text = NULL;
+  charcode = NULL;
   edge = NULL;
   len = size = 0;
   spaceAfter = gFalse;
@@ -229,17 +231,20 @@
 
 TextWord::~TextWord() {
   gfree(text);
+  gfree(charcode);
   gfree(edge);
 }
 
 void TextWord::addChar(GfxState *state, double x, double y,
-		       double dx, double dy, Unicode u) {
+		       double dx, double dy, CharCode c, Unicode u) {
   if (len == size) {
     size += 16;
     text = (Unicode *)grealloc(text, size * sizeof(Unicode));
+    charcode = (Unicode *)grealloc(charcode, size * sizeof(CharCode));
     edge = (double *)grealloc(edge, (size + 1) * sizeof(double));
   }
   text[len] = u;
+  charcode[len] = c;
   switch (rot) {
   case 0:
     if (len == 0) {
@@ -291,10 +296,12 @@
   if (len + word->len > size) {
     size = len + word->len;
     text = (Unicode *)grealloc(text, size * sizeof(Unicode));
+    charcode = (CharCode *)grealloc(charcode, (size + 1) * sizeof(CharCode));
     edge = (double *)grealloc(edge, (size + 1) * sizeof(double));
   }
   for (i = 0; i < word->len; ++i) {
     text[len + i] = word->text[i];
+    charcode[len + i] = word->charcode[i];
     edge[len + i] = word->edge[i];
   }
   edge[len + word->len] = word->edge[word->len];
@@ -480,8 +487,6 @@
 TextLine::TextLine(TextBlock *blkA, int rotA, double baseA) {
   blk = blkA;
   rot = rotA;
-  xMin = yMin = 0;
-  xMax = yMax = -1;
   base = baseA;
   words = lastWord = NULL;
   text = NULL;
@@ -491,6 +496,8 @@
   convertedLen = 0;
   hyphenated = gFalse;
   next = NULL;
+  xMin = yMin = 0;
+  xMax = yMax = -1;
 }
 
 TextLine::~TextLine() {
@@ -1904,7 +1911,7 @@
     h1 /= uLen;
   }
   for (i = 0; i < uLen; ++i) {
-    curWord->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, u[i]);
+    curWord->addChar(state, x1 + i*w1, y1 + i*h1, w1, h1, c, u[i]);
   }
   ++curWord->charLen;
   ++charPos;
@@ -2974,6 +2981,394 @@
   return s;
 }
 
+class TextSelectionVisitor {
+public:
+  TextSelectionVisitor (TextPage *page);
+  virtual ~TextSelectionVisitor () { }
+  virtual void visitBlock (TextBlock *block,
+			   TextLine *begin,
+			   TextLine *end,
+			   PDFRectangle *selection) = 0;
+  virtual void visitLine (TextLine *line, 
+			  TextWord *begin,
+			  TextWord *end,
+			  PDFRectangle *selection) = 0;
+  virtual void visitWord (TextWord *word, int begin, int end,
+			  PDFRectangle *selection) = 0;
+
+protected:
+  TextPage *page;
+};
+
+TextSelectionVisitor::TextSelectionVisitor (TextPage *page)
+  : page(page)
+{
+}
+
+
+
+
+#if 0
+class TextSelectionDumper : public TextSelectionVisitor {
+public:
+  virtual void visitBlock (TextBlock *block, 
+			   TextLine *begin,
+			   TextLine *end,
+			   PDFRectangle *selection) { };
+  virtual void visitLine (TextLine *line,
+			  TextWord *begin,
+			  TextWord *end,
+			  PDFRectangle *selection) { };
+  virtual void visitWord (TextWord *word, int begin, int end,
+			  PDFRectangle *selection);
+
+private:
+  GooString *result;
+  UnicodeMap *uMap;
+  char space[8], eol[16];
+  int spaceLen, eolLen;
+  double height;
+};
+
+TextSelectionDumper::TextSelectionDumper()
+{
+  result = new GooString();
+  uMap = globalParams->getTextEncoding();
+
+  // get the output encoding
+  if (data.uMap == NULL)
+    return data.result;
+
+  data.spaceLen = data.uMap->mapUnicode(0x20, data.space, sizeof(data.space));
+  data.eolLen = 0; // make gcc happy
+  switch (globalParams->getTextEOL()) {
+  case eolUnix:
+    data.eolLen = data.uMap->mapUnicode(0x0a, data.eol, sizeof(data.eol));
+    break;
+  case eolDOS:
+    data.eolLen = data.uMap->mapUnicode(0x0d, data.eol, sizeof(data.eol));
+    data.eolLen += data.uMap->mapUnicode(0x0a, data.eol + data.eolLen,
+					 sizeof(data.eol) - data.eolLen);
+    break;
+  case eolMac:
+    data.eolLen = data.uMap->mapUnicode(0x0d, data.eol, sizeof(data.eol));
+    break;
+  }
+}
+
+TextSelectionDumper::~TextSelectionDumper()
+{
+  data.uMap->decRefCnt();
+}
+
+void TextSelectionDumper::visitWord(TextWord *word, int first, int last,
+				    PDFRectangle *selection)
+{
+  for (i = first; i <= last; i++)
+    printf ("%c", word->text[i]);
+  printf ("\n");
+}
+
+#endif
+
+class TextSelectionSizer : public TextSelectionVisitor {
+public:
+  TextSelectionSizer(TextPage *page, double scale);
+  ~TextSelectionSizer() { }
+
+  virtual void visitBlock (TextBlock *block,
+			   TextLine *begin,
+			   TextLine *end,
+			   PDFRectangle *selection) { };
+  virtual void visitLine (TextLine *line, 
+			  TextWord *begin,
+			  TextWord *end,
+			  PDFRectangle *selection);
+  virtual void visitWord (TextWord *word, int begin, int end,
+			  PDFRectangle *selection) { };
+
+  GooList *getRegion () { return list; }
+
+private:
+  GooList *list;
+  double scale;
+};
+
+TextSelectionSizer::TextSelectionSizer(TextPage *page, double scale)
+  : TextSelectionVisitor(page),
+    scale(scale)
+{
+  list = new GooList();
+}
+
+void TextSelectionSizer::visitLine (TextLine *line, 
+				    TextWord *begin,
+				    TextWord *end,
+				    PDFRectangle *selection)
+{
+  PDFRectangle *rect;
+  double x1, y1, x2, y2, margin;
+  int i;
+
+  margin = (line->yMax - line->yMin) / 8;
+  x1 = floor (line->xMax * scale);
+  y1 = floor ((line->yMin - margin) * scale);
+  x2 = ceil (line->xMin * scale);
+  y2 = ceil ((line->yMax + margin) * scale);
+
+  for (i = 0; i < line->len; i++) {
+    if (selection->x1 < line->edge[i + 1] && line->edge[i] < x1)
+      x1 = floor (line->edge[i]);
+    if (line->edge[i] < selection->x2)
+      x2 = ceil (line->edge[i + 1]);
+  }
+
+  rect = new PDFRectangle (x1, y1, x2, y2);
+  list->append (rect);
+}
+
+
+class TextSelectionPainter : public TextSelectionVisitor {
+public:
+  TextSelectionPainter(TextPage *page,
+		       double scale,
+		       OutputDev *out,
+		       GfxColor &box_color,
+		       GfxColor &glyph_color);
+  ~TextSelectionPainter();
+
+  virtual void visitBlock (TextBlock *block,
+			   TextLine *begin,
+			   TextLine *end,
+			   PDFRectangle *selection) { };
+  virtual void visitLine (TextLine *line, 
+			  TextWord *begin,
+			  TextWord *end,
+			  PDFRectangle *selection);
+  virtual void visitWord (TextWord *word, int begin, int end,
+			  PDFRectangle *selection);
+
+private:
+  OutputDev *out;
+  GfxColor box_color, glyph_color;
+  GfxState *state;
+};
+
+TextSelectionPainter::TextSelectionPainter(TextPage *page,
+					   double scale,
+					   OutputDev *out,
+					   GfxColor &box_color,
+					   GfxColor &glyph_color)
+  : TextSelectionVisitor(page),
+    out(out),
+    box_color(box_color),
+    glyph_color(glyph_color)
+{
+  PDFRectangle box(0, 0, page->pageWidth, page->pageHeight);
+
+  state = new GfxState(72 * scale, 72 * scale, &box, 0, gFalse);
+
+  out->startPage (0, state);
+
+  state->setTextMat(1, 0, 0, -1, 0, 0);
+  state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+
+}
+
+TextSelectionPainter::~TextSelectionPainter()
+{
+  out->endPage ();
+
+  delete state;
+}
+
+void TextSelectionPainter::visitLine (TextLine *line,
+				      TextWord *begin,
+				      TextWord *end,
+				      PDFRectangle *selection)
+{
+  double x1, y1, x2, y2, margin;
+  int i;
+
+  state->setFillColor(&box_color);
+  out->updateFillColor(state);
+
+  margin = (line->yMax - line->yMin) / 8;
+  x1 = floor (line->xMax);
+  y1 = floor (line->yMin - margin);
+  x2 = ceil (line->xMin);
+  y2 = ceil (line->yMax + margin);
+
+  for (i = 0; i < line->len; i++) {
+    if (selection->x1 < line->edge[i + 1] && line->edge[i] < x1)
+      x1 = floor (line->edge[i]);
+    if (line->edge[i] < selection->x2)
+      x2 = ceil (line->edge[i + 1]);
+  }
+
+  state->moveTo(x1, y1);
+  state->lineTo(x2, y1);
+  state->lineTo(x2, y2);
+  state->lineTo(x1, y2);
+  state->closePath();
+
+  out->fill(state);
+  state->clearPath();
+}
+
+void TextSelectionPainter::visitWord (TextWord *word, int begin, int end,
+				      PDFRectangle *selection)
+{
+  GooString *string;
+  int i;
+
+  state->setFillColor(&glyph_color);
+  out->updateFillColor(state);
+  state->setFont(word->font->gfxFont, word->fontSize);
+  out->updateFont(state);
+
+  /* The only purpose of this string is to let the output device query
+   * it's length.  Might want to change this interface later. */
+
+  string = new GooString ((char *) word->charcode, end - begin);
+
+  out->beginString(state, string);
+
+  for (i = begin; i < end; i++)
+    out->drawChar(state, word->edge[i], word->base, 0, 0, 0, 0,
+		  word->charcode[i], NULL, 0);
+  
+  out->endString(state);
+}
+
+void TextWord::visitSelection(TextSelectionVisitor *visitor,
+			      PDFRectangle *selection) {
+  int i, begin, end;
+
+  begin = len + 1;
+  end = 0;
+  for (i = 0; i < len; i++) {
+    if (selection->x1 < edge[i + 1] && i < begin)
+      begin = i;
+    if (edge[i] < selection->x2)
+      end = i + 1;
+  }
+
+  visitor->visitWord (this, begin, end, selection);
+}
+
+void TextLine::visitSelection(TextSelectionVisitor *visitor,
+			      PDFRectangle *selection) {
+  TextWord *p, *begin, *end;
+
+  begin = NULL;
+  end = NULL;
+  for (p = words; p != NULL; p = p->next) {
+    if (selection->x1 < p->xMax && selection->y1 < p->yMax && begin == NULL)
+      begin = p;
+    if (selection->x2 > p->xMin && selection->y2 > p->yMin)
+      end = p->next;
+  }
+
+  visitor->visitLine (this, begin, end, selection);
+
+  for (p = begin; p != end; p = p->next)
+    p->visitSelection (visitor, selection);
+}
+
+void TextBlock::visitSelection(TextSelectionVisitor *visitor,
+			       PDFRectangle *selection) {
+  TextLine *p, *begin, *end;
+  PDFRectangle child_selection;
+
+  begin = NULL;
+  end = NULL;
+  for (p = lines; p != NULL; p = p->next) {
+    if (selection->x1 < p->xMax && selection->y1 < p->yMax && begin == NULL)
+      begin = p;
+    if (selection->x2 > p->xMin && selection->y2 > p->yMin)
+      end = p->next;
+  }
+
+  visitor->visitBlock (this, begin, end, selection);
+
+  for (p = begin; p != end; p = p->next) {
+    if (p == begin) {
+      child_selection.x1 = selection->x1;
+      child_selection.y1 = selection->y1;
+    } else {
+      child_selection.x1 = 0;
+      child_selection.y1 = 0;
+    }
+    if (p->next == end) {
+      child_selection.x2 = selection->x2;
+      child_selection.y2 = selection->y2;
+    } else {
+      child_selection.x2 = page->pageWidth;
+      child_selection.y2 = page->pageHeight;
+    }
+
+    p->visitSelection(visitor, &child_selection);
+  }
+}
+
+void TextPage::visitSelection(TextSelectionVisitor *visitor,
+			      PDFRectangle *selection)
+{
+  int i, begin, end;
+  PDFRectangle child_selection;
+
+  begin = nBlocks;
+  end = 0;
+  for (i = 0; i < nBlocks; i++) {
+    if (selection->x1 < blocks[i]->xMax && 
+	selection->y1 < blocks[i]->yMax && i < begin)
+      begin = i;
+    if (selection->x2 > blocks[i]->xMin && selection->y2 > blocks[i]->yMin)
+      end = i + 1;
+  }
+
+  for (i = begin; i < end; i++) {
+    if (i == begin) {
+      child_selection.x1 = selection->x1;
+      child_selection.y1 = selection->y1;
+    } else {
+      child_selection.x1 = 0;
+      child_selection.y1 = 0;
+    }
+    if (i + 1 == end) {
+      child_selection.x2 = selection->x2;
+      child_selection.y2 = selection->y2;
+    } else {
+      child_selection.x2 = pageWidth;
+      child_selection.y2 = pageHeight;
+    }
+
+    blocks[i]->visitSelection(visitor, &child_selection);
+  }
+}
+
+void TextPage::drawSelection(OutputDev *out,
+			     double scale,
+			     PDFRectangle *selection)
+{
+  GfxColor box_color = { 0x7c / 255.0, 0x99 / 255.0, 0xad / 255.0 };
+  GfxColor glyph_color = { 1.0, 1.0, 1.0 };
+  TextSelectionPainter painter(this, scale, out, box_color, glyph_color);
+
+  visitSelection(&painter, selection);
+}
+
+GooList *TextPage::getSelectionRegion(PDFRectangle *selection,
+				      double scale) {
+  TextSelectionSizer sizer(this, scale);
+  GooList *region;
+
+  visitSelection(&sizer, selection);
+
+  return sizer.getRegion();
+}
+
 GBool TextPage::findCharRange(int pos, int length,
 			      double *xMin, double *yMin,
 			      double *xMax, double *yMax) {
@@ -3516,6 +3911,17 @@
   return text->getText(xMin, yMin, xMax, yMax);
 }
 
+void TextOutputDev::drawSelection(OutputDev *out,
+				  double scale,
+				  PDFRectangle *selection) {
+  text->drawSelection(out, scale, selection);
+}
+
+GooList *TextOutputDev::getSelectionRegion(PDFRectangle *selection,
+					   double scale) {
+  return text->getSelectionRegion(selection, scale);
+}
+
 GBool TextOutputDev::findCharRange(int pos, int length,
 				   double *xMin, double *yMin,
 				   double *xMax, double *yMax) {

Index: TextOutputDev.h
===================================================================
RCS file: /cvs/poppler/poppler/poppler/TextOutputDev.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- TextOutputDev.h	2 Jun 2005 19:14:45 -0000	1.2
+++ TextOutputDev.h	29 Jun 2005 21:24:57 -0000	1.3
@@ -21,12 +21,14 @@
 
 class GooString;
 class GooList;
+class Gfx;
 class GfxFont;
 class GfxState;
 class UnicodeMap;
 class TextBlock;
 class TextPage;
 class TextLineFrag;
+class TextSelectionVisitor;
 
 //------------------------------------------------------------------------
 
@@ -53,6 +55,7 @@
 
   friend class TextWord;
   friend class TextPage;
+  friend class TextSelectionPainter;
 };
 
 //------------------------------------------------------------------------
@@ -71,7 +74,7 @@
 
   // Add a character to the word.
   void addChar(GfxState *state, double x, double y,
-	       double dx, double dy, Unicode u);
+	       double dx, double dy, CharCode c, Unicode u);
 
   // Merge <word> onto the end of <this>.
   void merge(TextWord *word);
@@ -86,6 +89,9 @@
 
   static int cmpYX(const void *p1, const void *p2);
 
+  void visitSelection(TextSelectionVisitor *visitor,
+		      PDFRectangle *selection);
+
 #if TEXTOUT_WORD_LIST
   int getLength() { return len; }
   Unicode getChar(int idx) { return text[idx]; }
@@ -107,6 +113,7 @@
   double yMin, yMax;		// bounding box y coordinates
   double base;			// baseline x or y coordinate
   Unicode *text;		// the text
+  CharCode *charcode;		// glyph indices
   double *edge;			// "near" edge x or y coord of each char
 				//   (plus one extra entry for the last char)
   int len;			// length of text and edge arrays
@@ -132,6 +139,7 @@
   friend class TextFlow;
   friend class TextWordList;
   friend class TextPage;
+  friend class TextSelectionPainter;
 };
 
 //------------------------------------------------------------------------
@@ -164,6 +172,8 @@
   friend class TextPage;
 };
 
+struct TextFlowData;
+
 //------------------------------------------------------------------------
 // TextLine
 //------------------------------------------------------------------------
@@ -195,6 +205,9 @@
 
   void coalesce(UnicodeMap *uMap);
 
+  void visitSelection(TextSelectionVisitor *visitor,
+		      PDFRectangle *selection);
+
 private:
 
   TextBlock *blk;		// parent block
@@ -219,6 +232,9 @@
   friend class TextFlow;
   friend class TextWordList;
   friend class TextPage;
+
+  friend class TextSelectionPainter;
+  friend class TextSelectionSizer;
 };
 
 //------------------------------------------------------------------------
@@ -250,6 +266,9 @@
   // primary rotation.
   GBool isBelow(TextBlock *blk);
 
+  void visitSelection(TextSelectionVisitor *visitor,
+		      PDFRectangle *selection);
+
 private:
 
   TextPage *page;		// the parent page
@@ -275,6 +294,7 @@
   friend class TextFlow;
   friend class TextWordList;
   friend class TextPage;
+  friend class TextSelectionPainter;
 };
 
 //------------------------------------------------------------------------
@@ -394,7 +414,16 @@
 
   // Get the text which is inside the specified rectangle.
   GooString *getText(double xMin, double yMin,
-		   double xMax, double yMax);
+		     double xMax, double yMax);
+
+  void visitSelection(TextSelectionVisitor *visitor,
+		      PDFRectangle *selection);
+
+  void drawSelection(OutputDev *out,
+		     double scale,
+		     PDFRectangle *selection);
+
+  GooList *getSelectionRegion(PDFRectangle *selection, double scale);
 
   // Find a string by character position and length.  If found, sets
   // the text bounding rectangle and returns true; otherwise returns
@@ -457,6 +486,7 @@
   friend class TextBlock;
   friend class TextFlow;
   friend class TextWordList;
+  friend class TextSelectionPainter;
 };
 
 //------------------------------------------------------------------------
@@ -548,6 +578,10 @@
 		      double *xMin, double *yMin,
 		      double *xMax, double *yMax);
 
+  void drawSelection(OutputDev *out, double scale, PDFRectangle *selection);
+
+  GooList *getSelectionRegion(PDFRectangle *selection, double scale);
+
 #if TEXTOUT_WORD_LIST
   // Build a flat word list, in content stream order (if
   // this->rawOrder is true), physical layout order (if



More information about the poppler mailing list