summaryrefslogtreecommitdiff
path: root/poppler-0.30.0-rotated-words-selection.patch
diff options
context:
space:
mode:
Diffstat (limited to 'poppler-0.30.0-rotated-words-selection.patch')
-rw-r--r--poppler-0.30.0-rotated-words-selection.patch285
1 files changed, 285 insertions, 0 deletions
diff --git a/poppler-0.30.0-rotated-words-selection.patch b/poppler-0.30.0-rotated-words-selection.patch
new file mode 100644
index 0000000..33c6b8e
--- /dev/null
+++ b/poppler-0.30.0-rotated-words-selection.patch
@@ -0,0 +1,285 @@
+From 0ab1f29d4ce315b0fca260c0e0f3007024d00342 Mon Sep 17 00:00:00 2001
+From: Marek Kasik <mkasik@redhat.com>
+Date: Tue, 28 Jan 2014 15:13:24 +0100
+Subject: [PATCH] TextOutputDev: Respect orientation when selecting words
+
+Take rotation into account when visiting selection.
+This doesn't fix all problems (there are still problems
+on line and block levels).
+
+https://bugs.freedesktop.org/show_bug.cgi?id=16619
+---
+ poppler/TextOutputDev.cc | 193 ++++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 150 insertions(+), 43 deletions(-)
+
+diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
+index 7c2ca78..e93908c 100644
+--- a/poppler/TextOutputDev.cc
++++ b/poppler/TextOutputDev.cc
+@@ -178,6 +178,12 @@
+ // (Or 1/tan(angle) for 90/270 degrees.)
+ #define diagonalThreshold 0.1
+
++// Returns whether x is between a and b or equal to a or b.
++// a and b don't need to be sorted.
++#define XBetweenAB(x,a,b) (!(((x) > (a) && (x) > (b)) || \
++ ((x) < (a) && (x) < (b))) ? \
++ true : false)
++
+ namespace {
+
+ inline bool isAscii7 (Unicode uchar) {
+@@ -4411,11 +4417,37 @@ void TextSelectionSizer::visitLine (TextLine *line,
+ PDFRectangle *rect;
+ double x1, y1, x2, y2, margin;
+
+- margin = (line->yMax - line->yMin) / 8;
+- x1 = line->edge[edge_begin];
+- y1 = line->yMin - margin;
+- x2 = line->edge[edge_end];
+- y2 = line->yMax + margin;
++ switch (line->rot) {
++ default:
++ case 0:
++ margin = (line->yMax - line->yMin) / 8;
++ x1 = line->edge[edge_begin];
++ x2 = line->edge[edge_end];
++ y1 = line->yMin - margin;
++ y2 = line->yMax + margin;
++ break;
++ case 1:
++ margin = (line->xMax - line->xMin) / 8;
++ x1 = line->xMin - margin;
++ x2 = line->xMax + margin;
++ y1 = line->edge[edge_begin];
++ y2 = line->edge[edge_end];
++ break;
++ case 2:
++ margin = (line->yMax - line->yMin) / 8;
++ x1 = line->edge[edge_end];
++ x2 = line->edge[edge_begin];
++ y1 = line->yMin - margin;
++ y2 = line->yMax + margin;
++ break;
++ case 3:
++ margin = (line->xMax - line->xMin) / 8;
++ x1 = line->xMin - margin;
++ x2 = line->xMax + margin;
++ y1 = line->edge[edge_end];
++ y2 = line->edge[edge_begin];
++ break;
++ }
+
+ rect = new PDFRectangle (floor (x1 * scale),
+ floor (y1 * scale),
+@@ -4499,19 +4531,56 @@ void TextSelectionPainter::visitLine (TextLine *line,
+ {
+ double x1, y1, x2, y2, margin;
+
+- margin = (line->yMax - line->yMin) / 8;
+- x1 = floor (line->edge[edge_begin]);
+- y1 = floor (line->yMin - margin);
+- x2 = ceil (line->edge[edge_end]);
+- y2 = ceil (line->yMax + margin);
++ switch (line->rot) {
++ default:
++ case 0:
++ margin = (line->yMax - line->yMin) / 8;
++ x1 = line->edge[edge_begin];
++ x2 = line->edge[edge_end];
++ y1 = line->yMin - margin;
++ y2 = line->yMax + margin;
++ break;
++ case 1:
++ margin = (line->xMax - line->xMin) / 8;
++ x1 = line->xMin - margin;
++ x2 = line->xMax + margin;
++ y1 = line->edge[edge_begin];
++ y2 = line->edge[edge_end];
++ break;
++ case 2:
++ margin = (line->yMax - line->yMin) / 8;
++ x1 = line->edge[edge_end];
++ x2 = line->edge[edge_begin];
++ y1 = line->yMin - margin;
++ y2 = line->yMax + margin;
++ break;
++ case 3:
++ margin = (line->xMax - line->xMin) / 8;
++ x1 = line->xMin - margin;
++ x2 = line->xMax + margin;
++ y1 = line->edge[edge_end];
++ y2 = line->edge[edge_begin];
++ break;
++ }
++
++ ctm.transform(x1, y1, &x1, &y1);
++ ctm.transform(x2, y2, &x2, &y2);
+
+- ctm.transform(line->edge[edge_begin], line->yMin - margin, &x1, &y1);
+- ctm.transform(line->edge[edge_end], line->yMax + margin, &x2, &y2);
++ if (x1 < x2) {
++ x1 = floor (x1);
++ x2 = ceil (x2);
++ } else {
++ x1 = ceil (x1);
++ x2 = floor (x2);
++ }
+
+- x1 = floor (x1);
+- y1 = floor (y1);
+- x2 = ceil (x2);
+- y2 = ceil (y2);
++ if (y1 < y2) {
++ y1 = floor (y1);
++ y2 = ceil (y2);
++ } else {
++ y1 = ceil (y1);
++ y2 = floor (y2);
++ }
+
+ ictm.transform(x1, y1, &x1, &y1);
+ ictm.transform(x2, y2, &x2, &y2);
+@@ -4589,17 +4658,27 @@ void TextWord::visitSelection(TextSelectionVisitor *visitor,
+ SelectionStyle style)
+ {
+ int i, begin, end;
+- double mid;
++ double mid, s1, s2;
++
++ if (rot == 0 || rot == 2) {
++ s1 = selection->x1;
++ s2 = selection->x2;
++ } else {
++ s1 = selection->y1;
++ s2 = selection->y2;
++ }
+
+ begin = len;
+ end = 0;
+ for (i = 0; i < len; i++) {
+ mid = (edge[i] + edge[i + 1]) / 2;
+- if (selection->x1 < mid || selection->x2 < mid)
+- if (i < begin)
+- begin = i;
+- if (mid < selection->x1 || mid < selection->x2)
+- end = i + 1;
++ if (XBetweenAB (mid, s1, s2))
++ {
++ if (i < begin)
++ begin = i;
++
++ end = i + 1;
++ }
+ }
+
+ /* Skip empty selection. */
+@@ -4615,30 +4694,41 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor,
+ TextWord *p, *begin, *end, *current;
+ int i, edge_begin, edge_end;
+ PDFRectangle child_selection;
++ double s1, s2, p_min, p_max;
++
++ if (rot == 0 || rot == 2) {
++ s1 = selection->x1;
++ s2 = selection->x2;
++ } else {
++ s1 = selection->y1;
++ s2 = selection->y2;
++ }
+
+ begin = nullptr;
+ end = nullptr;
+ current = nullptr;
+ for (p = words; p != nullptr; p = p->next) {
++ if (rot == 0 || rot == 2) {
++ p_min = p->xMin;
++ p_max = p->xMax;
++ } else {
++ p_min = p->yMin;
++ p_max = p->yMax;
++ }
++
+ if (blk->page->primaryLR) {
+- if ((selection->x1 < p->xMax) ||
+- (selection->x2 < p->xMax))
+- if (begin == nullptr)
+- begin = p;
++ if (((s1 < p_max) || (s2 < p_max)) && begin == nullptr)
++ begin = p;
+
+- if (((selection->x1 > p->xMin) ||
+- (selection->x2 > p->xMin)) && (begin != nullptr)) {
++ if (((s1 > p_min) || (s2 > p_min)) && begin != nullptr) {
+ end = p->next;
+ current = p;
+ }
+ } else {
+- if ((selection->x1 > p->xMin) ||
+- (selection->x2 > p->xMin))
+- if (begin == nullptr)
+- begin = p;
++ if (((s1 > p_min) || (s2 > p_min)) && begin == nullptr)
++ begin = p;
+
+- if (((selection->x1 < p->xMax) ||
+- (selection->x2 < p->xMax)) && (begin != nullptr)) {
++ if (((s1 < p_max) || (s2 < p_max)) && begin != nullptr) {
+ end = p->next;
+ current = p;
+ }
+@@ -4650,23 +4740,42 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor,
+
+ child_selection = *selection;
+ if (style == selectionStyleWord) {
+- child_selection.x1 = begin ? begin->xMin : xMin;
+- if (end && end->xMax != -1) {
+- child_selection.x2 = current->xMax;
++ if (rot == 0 || rot == 2) {
++ child_selection.x1 = begin ? begin->xMin : xMin;
++ if (end && end->xMax != -1) {
++ child_selection.x2 = current->xMax;
++ } else {
++ child_selection.x2 = xMax;
++ }
+ } else {
+- child_selection.x2 = xMax;
++ child_selection.y1 = begin ? begin->yMin : yMin;
++ if (end && end->yMax != -1) {
++ child_selection.y2 = current->yMax;
++ } else {
++ child_selection.y2 = yMax;
++ }
+ }
+ }
+
++ if (rot == 0 || rot == 2) {
++ s1 = child_selection.x1;
++ s2 = child_selection.x2;
++ } else {
++ s1 = child_selection.y1;
++ s2 = child_selection.y2;
++ }
++
+ edge_begin = len;
+ edge_end = 0;
+ for (i = 0; i < len; i++) {
+ double mid = (edge[i] + edge[i + 1]) / 2;
+- if (child_selection.x1 < mid || child_selection.x2 < mid)
+- if (i < edge_begin)
+- edge_begin = i;
+- if (mid < child_selection.x2 || mid < child_selection.x1)
+- edge_end = i + 1;
++ if (XBetweenAB (mid, s1, s2))
++ {
++ if (i < edge_begin)
++ edge_begin = i;
++
++ edge_end = i + 1;
++ }
+ }
+
+ /* Skip empty selection. */
+--
+1.8.4.2
+