From a5d38f8b35d9fd886127b7f3e0da0420fc9d8e1d Mon Sep 17 00:00:00 2001 From: Marek Kasik Date: Thu, 26 Mar 2015 17:05:01 +0100 Subject: [PATCH] Respect orientation when selecting words Resolves: #1185007 --- poppler-0.30.0-rotated-words-selection.patch | 285 +++++++++++++++++++ poppler.spec | 10 +- 2 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 poppler-0.30.0-rotated-words-selection.patch 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..87d553b --- /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 +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 +@@ -173,6 +173,12 @@ + // Max distance between edge of text and edge of link border + #define hyperlinkSlack 2 + ++// 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))) ? \ ++ gTrue : gFalse) ++ + //------------------------------------------------------------------------ + // TextUnderline + //------------------------------------------------------------------------ +@@ -4222,11 +4228,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), +@@ -4310,19 +4341,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); +@@ -4400,17 +4467,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. */ +@@ -4426,30 +4503,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 = NULL; + end = NULL; + current = NULL; + for (p = words; p != NULL; 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 == NULL) +- begin = p; ++ if (((s1 < p_max) || (s2 < p_max)) && begin == NULL) ++ begin = p; + +- if (((selection->x1 > p->xMin) || +- (selection->x2 > p->xMin)) && (begin != NULL)) { ++ if (((s1 > p_min) || (s2 > p_min)) && begin != NULL) { + end = p->next; + current = p; + } + } else { +- if ((selection->x1 > p->xMin) || +- (selection->x2 > p->xMin)) +- if (begin == NULL) +- begin = p; ++ if (((s1 > p_min) || (s2 > p_min)) && begin == NULL) ++ begin = p; + +- if (((selection->x1 < p->xMax) || +- (selection->x2 < p->xMax)) && (begin != NULL)) { ++ if (((s1 < p_max) || (s2 < p_max)) && begin != NULL) { + end = p->next; + current = p; + } +@@ -4461,23 +4549,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 + diff --git a/poppler.spec b/poppler.spec index c211685..edda4d0 100644 --- a/poppler.spec +++ b/poppler.spec @@ -1,12 +1,15 @@ Summary: PDF rendering library Name: poppler Version: 0.30.0 -Release: 3%{?dist} +Release: 4%{?dist} License: (GPLv2 or GPLv3) and GPLv2+ and LGPLv2+ and MIT Group: Development/Libraries URL: http://poppler.freedesktop.org/ Source0: http://poppler.freedesktop.org/poppler-%{version}.tar.xz +# https://bugzilla.redhat.com/show_bug.cgi?id=1185007 +Patch0: poppler-0.30.0-rotated-words-selection.patch + ## upstreamable patches # fix configure checks for moc versions Patch50: poppler-0.24.2-mocversiongrep.patch @@ -143,6 +146,7 @@ Requires: %{name}-glib%{?_isa} = %{version}-%{release} %prep %setup -q +%patch0 -p1 -b .rotated-words-selection %patch50 -p1 -b .mocversiongrep @@ -278,6 +282,10 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %changelog +* Thu Mar 26 2015 Marek Kasik - 0.30.0-4 +- Respect orientation when selecting words +- Resolves: #1185007 + * Sat Feb 21 2015 Till Maas - 0.30.0-3 - Rebuilt for Fedora 23 Change https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code