poppler/TextOutputDev.cc | 109 +++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 40 deletions(-)
New commits: commit b3ff3f2c3e131556d2b27cbe52f0ddbbb4820c19 Author: Jason Crain <[email protected]> Date: Thu Jun 20 21:47:13 2013 -0500 Draw glyphs after selection background When multiple lines of text are selected, TextSelectionPainter will draw selections over each other, hiding the previous line with the selection background of the current line. This patch changes TextSelectionPainter so that glyphs are drawn only after the entire background is drawn. https://bugs.freedesktop.org/show_bug.cgi?id=65989 diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc index 801f347..fe051f6 100644 --- a/poppler/TextOutputDev.cc +++ b/poppler/TextOutputDev.cc @@ -4257,11 +4257,28 @@ public: PDFRectangle *selection); virtual void visitWord (TextWord *word, int begin, int end, PDFRectangle *selection); + void endPage(); private: OutputDev *out; GfxColor *box_color, *glyph_color; GfxState *state; + GooList *selectionList; + Matrix ctm, ictm; + + class TextSelection { + public: + TextSelection(TextWord *word, int begin, int end) + : word(word), + begin(begin), + end(end) + { + } + + TextWord *word; + int begin; + int end; + }; }; TextSelectionPainter::TextSelectionPainter(TextPage *page, @@ -4277,18 +4294,23 @@ TextSelectionPainter::TextSelectionPainter(TextPage *page, { PDFRectangle box(0, 0, page->pageWidth, page->pageHeight); + selectionList = new GooList(); state = new GfxState(72 * scale, 72 * scale, &box, rotation, gFalse); - out->startPage (0, state, NULL); + state->getCTM(&ctm); + ctm.invertTo(&ictm); + + out->startPage(0, state, NULL); out->setDefaultCTM (state->getCTM()); state->setFillColorSpace(new GfxDeviceRGBColorSpace()); + state->setFillColor(box_color); + out->updateFillColor(state); } TextSelectionPainter::~TextSelectionPainter() { - out->endPage (); - + deleteGooList(selectionList, TextSelection); delete state; } @@ -4300,10 +4322,6 @@ void TextSelectionPainter::visitLine (TextLine *line, PDFRectangle *selection) { double x1, y1, x2, y2, margin; - Matrix ctm, ictm; - - state->setFillColor(box_color); - out->updateFillColor(state); margin = (line->yMax - line->yMin) / 8; x1 = floor (line->edge[edge_begin]); @@ -4311,7 +4329,6 @@ void TextSelectionPainter::visitLine (TextLine *line, x2 = ceil (line->edge[edge_end]); y2 = ceil (line->yMax + margin); - state->getCTM (&ctm); ctm.transform(line->edge[edge_begin], line->yMin - margin, &x1, &y1); ctm.transform(line->edge[edge_end], line->yMax + margin, &x2, &y2); @@ -4320,7 +4337,6 @@ void TextSelectionPainter::visitLine (TextLine *line, x2 = ceil (x2); y2 = ceil (y2); - ctm.invertTo (&ictm); ictm.transform(x1, y1, &x1, &y1); ictm.transform(x2, y2, &x2, &y2); @@ -4329,47 +4345,59 @@ void TextSelectionPainter::visitLine (TextLine *line, 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) { - state->setFillColor(glyph_color); - out->updateFillColor(state); - - while (begin < end) { - TextFontInfo *font = word->font[begin]; - font->gfxFont->incRefCnt(); - Matrix *mat = &word->textMat[begin]; - - state->setTextMat(mat->m[0], mat->m[1], mat->m[2], mat->m[3], 0, 0); - state->setFont(font->gfxFont, 1); - out->updateFont(state); + selectionList->append(new TextSelection(word, begin, end)); +} - int fEnd = begin + 1; - while (fEnd < end && font->matches(word->font[fEnd]) && - mat->m[0] == word->textMat[fEnd].m[0] && - mat->m[1] == word->textMat[fEnd].m[1] && - mat->m[2] == word->textMat[fEnd].m[2] && - mat->m[3] == word->textMat[fEnd].m[3]) - fEnd++; +void TextSelectionPainter::endPage() +{ + out->fill(state); + state->clearPath(); - /* The only purpose of this string is to let the output device query - * it's length. Might want to change this interface later. */ - GooString *string = new GooString ((char *) word->charcode, fEnd - begin); - out->beginString(state, string); + state->setFillColor(glyph_color); + out->updateFillColor(state); - for (int i = begin; i < fEnd; i++) { - out->drawChar(state, word->textMat[i].m[4], word->textMat[i].m[5], 0, 0, 0, 0, - word->charcode[i], 1, NULL, 0); + for (int i = 0; i < selectionList->getLength(); i++) { + TextSelection *sel = (TextSelection *) selectionList->get(i); + int begin = sel->begin; + + while (begin < sel->end) { + TextFontInfo *font = sel->word->font[begin]; + font->gfxFont->incRefCnt(); + Matrix *mat = &sel->word->textMat[begin]; + + state->setTextMat(mat->m[0], mat->m[1], mat->m[2], mat->m[3], 0, 0); + state->setFont(font->gfxFont, 1); + out->updateFont(state); + + int fEnd = begin + 1; + while (fEnd < sel->end && font->matches(sel->word->font[fEnd]) && + mat->m[0] == sel->word->textMat[fEnd].m[0] && + mat->m[1] == sel->word->textMat[fEnd].m[1] && + mat->m[2] == sel->word->textMat[fEnd].m[2] && + mat->m[3] == sel->word->textMat[fEnd].m[3]) + fEnd++; + + /* The only purpose of this string is to let the output device query + * it's length. Might want to change this interface later. */ + GooString *string = new GooString ((char *) sel->word->charcode, fEnd - begin); + out->beginString(state, string); + + for (int i = begin; i < fEnd; i++) { + out->drawChar(state, sel->word->textMat[i].m[4], sel->word->textMat[i].m[5], 0, 0, 0, 0, + sel->word->charcode[i], 1, NULL, 0); + } + out->endString(state); + delete string; + begin = fEnd; } - out->endString(state); - delete string; - begin = fEnd; } + + out->endPage (); } void TextWord::visitSelection(TextSelectionVisitor *visitor, @@ -4715,6 +4743,7 @@ void TextPage::drawSelection(OutputDev *out, out, box_color, glyph_color); visitSelection(&painter, selection, style); + painter.endPage(); } GooList *TextPage::getSelectionRegion(PDFRectangle *selection, _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
