aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-02-20 22:28:58 +0100
committerJay Berkenbilt <ejb@ql.org>2021-02-20 22:29:34 +0100
commit35dd11f3560f820d01da9acb6c5425afcdeaea93 (patch)
treea6d3ac82fa903550d52e4911dcf547320764a40f
parent71e86272859aa2794263cc59446a20a826d6d3aa (diff)
downloadqpdf-35dd11f3560f820d01da9acb6c5425afcdeaea93.tar.zst
Allow --rotate=0
-rw-r--r--ChangeLog4
-rw-r--r--libqpdf/QPDFObjectHandle.cc2
-rw-r--r--manual/qpdf-manual.xml8
-rw-r--r--qpdf/qpdf.cc9
-rw-r--r--qpdf/qtest/qpdf.test10
-rw-r--r--qpdf/qtest/qpdf/unrotated.pdf925
6 files changed, 952 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index baf568c4..c3b6629e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2021-02-20 Jay Berkenbilt <ejb@ql.org>
+
+ * Allow --rotate=0 to clear rotation from a page.
+
2021-02-18 Jay Berkenbilt <ejb@ql.org>
* Add QPDFAcroFormDocumentHelper::addFormField, which adds a new
diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc
index 8f7399f2..b0ae75f1 100644
--- a/libqpdf/QPDFObjectHandle.cc
+++ b/libqpdf/QPDFObjectHandle.cc
@@ -1579,6 +1579,8 @@ QPDFObjectHandle::rotatePage(int angle, bool relative)
new_angle += old_angle;
}
new_angle = (new_angle + 360) % 360;
+ // Make this explicit even with new_angle == 0 since /Rotate can
+ // be inherited.
replaceKey("/Rotate", QPDFObjectHandle::newInteger(new_angle));
}
diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml
index dd03f8d8..bffd52cb 100644
--- a/manual/qpdf-manual.xml
+++ b/manual/qpdf-manual.xml
@@ -1008,7 +1008,7 @@ make
linkend="ref.page-selection"/>. If the page range is omitted,
the rotation is applied to all pages. The
<option>angle</option> portion of the parameter may be either
- 90, 180, or 270. If preceded by <option>+</option> or
+ 0, 90, 180, or 270. If preceded by <option>+</option> or
<option>-</option>, the angle is added to or subtracted from
the specified pages' original rotations. This is almost always
what you want. Otherwise the pages' rotations are set to the
@@ -5175,6 +5175,12 @@ print "\n";
from the given files.
</para>
</listitem>
+ <listitem>
+ <para>
+ It is now valid to provide <option>--rotate=0</option> to
+ clear rotation from a page.
+ </para>
+ </listitem>
</itemizedlist>
</listitem>
<listitem>
diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc
index 0c0b344f..2f910f22 100644
--- a/qpdf/qpdf.cc
+++ b/qpdf/qpdf.cc
@@ -1374,8 +1374,8 @@ ArgParser::argHelp()
<< " concatenated\n"
<< "--flatten-rotation move page rotation from /Rotate key to content\n"
<< "--rotate=[+|-]angle[:page-range]\n"
- << " rotate each specified page 90, 180, or 270 degrees;\n"
- << " rotate all pages if no page range is given\n"
+ << " rotate each specified page 0, 90, 180, or 270\n"
+ << " degrees; rotate all pages if no page range is given\n"
<< "--split-pages=[n] write each output page to a separate file\n"
<< "--overlay options -- overlay pages from another file\n"
<< "--underlay options -- underlay pages from another file\n"
@@ -1399,7 +1399,7 @@ ArgParser::argHelp()
<< "or investigatory purposes. See manual for further discussion.\n"
<< "\n"
<< "The --rotate flag can be used to specify pages to rotate pages either\n"
- << "90, 180, or 270 degrees. The page range is specified in the same\n"
+ << "0, 90, 180, or 270 degrees. The page range is specified in the same\n"
<< "format as with the --pages option, described below. Repeat the option\n"
<< "to rotate multiple groups of pages. If the angle is preceded by + or -,\n"
<< "it is added to or subtracted from the original rotation. Otherwise, the\n"
@@ -3448,7 +3448,8 @@ ArgParser::parseRotationParameter(std::string const& parameter)
// ignore
}
if (range_valid &&
- ((angle_str == "90") || (angle_str == "180") || (angle_str == "270")))
+ ((angle_str == "0") ||(angle_str == "90") ||
+ (angle_str == "180") || (angle_str == "270")))
{
int angle = QUtil::string_to_int(angle_str.c_str());
if (relative == -1)
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
index 4ed3ac33..90e7730f 100644
--- a/qpdf/qtest/qpdf.test
+++ b/qpdf/qtest/qpdf.test
@@ -2241,7 +2241,7 @@ $td->runtest("explicit keep files open = n",
show_ntests();
# ----------
$td->notify("--- Rotate Pages ---");
-$n_tests += 4;
+$n_tests += 6;
# Do absolute, positive, and negative on ranges that include
# inherited and non-inherited.
# Pages 11-15 inherit /Rotate 90
@@ -2258,6 +2258,14 @@ $td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "rotated.pdf"});
+$td->runtest("remove rotation",
+ {$td->COMMAND => "qpdf --static-id rotated.pdf a.pdf" .
+ " --qdf --no-original-object-ids --rotate=0"},
+ {$td->STRING => "", $td->EXIT_STATUS => 0});
+$td->runtest("check output",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "unrotated.pdf"});
+
$td->runtest("rotate all pages",
{$td->COMMAND =>
"qpdf --static-id --rotate=180 minimal.pdf a.pdf"},
diff --git a/qpdf/qtest/qpdf/unrotated.pdf b/qpdf/qtest/qpdf/unrotated.pdf
new file mode 100644
index 00000000..6341f29c
--- /dev/null
+++ b/qpdf/qtest/qpdf/unrotated.pdf
@@ -0,0 +1,925 @@
+%PDF-1.4
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 3 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+<<
+ /CreationDate (D:20120721200217)
+ /Producer (Apex PDFWriter)
+>>
+endobj
+
+3 0 obj
+<<
+ /Count 20
+ /Kids [
+ 4 0 R
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ 9 0 R
+ 10 0 R
+ 11 0 R
+ 12 0 R
+ 13 0 R
+ 14 0 R
+ 15 0 R
+ 16 0 R
+ 17 0 R
+ 18 0 R
+ 19 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+4 0 obj
+<<
+ /Contents 20 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+5 0 obj
+<<
+ /Contents 23 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+6 0 obj
+<<
+ /Contents 25 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+7 0 obj
+<<
+ /Contents 27 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 5
+8 0 obj
+<<
+ /Contents 29 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 6
+9 0 obj
+<<
+ /Contents 31 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 7
+10 0 obj
+<<
+ /Contents 33 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 8
+11 0 obj
+<<
+ /Contents 35 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 9
+12 0 obj
+<<
+ /Contents 37 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 10
+13 0 obj
+<<
+ /Contents 39 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+14 0 obj
+<<
+ /Count 5
+ /Kids [
+ 41 0 R
+ 42 0 R
+ 43 0 R
+ 44 0 R
+ 45 0 R
+ ]
+ /Parent 3 0 R
+ /Rotate 90
+ /Type /Pages
+>>
+endobj
+
+%% Page 16
+15 0 obj
+<<
+ /Contents 46 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 17
+16 0 obj
+<<
+ /Contents 48 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 18
+17 0 obj
+<<
+ /Contents 50 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 19
+18 0 obj
+<<
+ /Contents 52 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 20
+19 0 obj
+<<
+ /Contents 54 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 3 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+20 0 obj
+<<
+ /Length 21 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
+endstream
+endobj
+
+21 0 obj
+47
+endobj
+
+22 0 obj
+<<
+ /BaseFont /Times-Roman
+ /Encoding /WinAnsiEncoding
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+%% Contents for page 2
+23 0 obj
+<<
+ /Length 24 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
+endstream
+endobj
+
+24 0 obj
+47
+endobj
+
+%% Contents for page 3
+25 0 obj
+<<
+ /Length 26 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
+endstream
+endobj
+
+26 0 obj
+47
+endobj
+
+%% Contents for page 4
+27 0 obj
+<<
+ /Length 28 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
+endstream
+endobj
+
+28 0 obj
+47
+endobj
+
+%% Contents for page 5
+29 0 obj
+<<
+ /Length 30 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
+endstream
+endobj
+
+30 0 obj
+47
+endobj
+
+%% Contents for page 6
+31 0 obj
+<<
+ /Length 32 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
+endstream
+endobj
+
+32 0 obj
+47
+endobj
+
+%% Contents for page 7
+33 0 obj
+<<
+ /Length 34 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
+endstream
+endobj
+
+34 0 obj
+47
+endobj
+
+%% Contents for page 8
+35 0 obj
+<<
+ /Length 36 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
+endstream
+endobj
+
+36 0 obj
+47
+endobj
+
+%% Contents for page 9
+37 0 obj
+<<
+ /Length 38 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
+endstream
+endobj
+
+38 0 obj
+47
+endobj
+
+%% Contents for page 10
+39 0 obj
+<<
+ /Length 40 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 10) Tj ET
+endstream
+endobj
+
+40 0 obj
+48
+endobj
+
+%% Page 11
+41 0 obj
+<<
+ /Contents 56 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 14 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 12
+42 0 obj
+<<
+ /Contents 58 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 14 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 13
+43 0 obj
+<<
+ /Contents 60 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 14 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 14
+44 0 obj
+<<
+ /Contents 62 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 14 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Page 15
+45 0 obj
+<<
+ /Contents 64 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 14 0 R
+ /Resources <<
+ /Font <<
+ /F1 22 0 R
+ >>
+ /ProcSet [
+ /PDF
+ /Text
+ ]
+ >>
+ /Rotate 0
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 16
+46 0 obj
+<<
+ /Length 47 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 16) Tj ET
+endstream
+endobj
+
+47 0 obj
+48
+endobj
+
+%% Contents for page 17
+48 0 obj
+<<
+ /Length 49 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 17) Tj ET
+endstream
+endobj
+
+49 0 obj
+48
+endobj
+
+%% Contents for page 18
+50 0 obj
+<<
+ /Length 51 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 18) Tj ET
+endstream
+endobj
+
+51 0 obj
+48
+endobj
+
+%% Contents for page 19
+52 0 obj
+<<
+ /Length 53 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 19) Tj ET
+endstream
+endobj
+
+53 0 obj
+48
+endobj
+
+%% Contents for page 20
+54 0 obj
+<<
+ /Length 55 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 20) Tj ET
+endstream
+endobj
+
+55 0 obj
+48
+endobj
+
+%% Contents for page 11
+56 0 obj
+<<
+ /Length 57 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 11) Tj ET
+endstream
+endobj
+
+57 0 obj
+48
+endobj
+
+%% Contents for page 12
+58 0 obj
+<<
+ /Length 59 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 12) Tj ET
+endstream
+endobj
+
+59 0 obj
+48
+endobj
+
+%% Contents for page 13
+60 0 obj
+<<
+ /Length 61 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 13) Tj ET
+endstream
+endobj
+
+61 0 obj
+48
+endobj
+
+%% Contents for page 14
+62 0 obj
+<<
+ /Length 63 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 14) Tj ET
+endstream
+endobj
+
+63 0 obj
+48
+endobj
+
+%% Contents for page 15
+64 0 obj
+<<
+ /Length 65 0 R
+>>
+stream
+BT /F1 15 Tf 72 720 Td (Original page 15) Tj ET
+endstream
+endobj
+
+65 0 obj
+48
+endobj
+
+xref
+0 66
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000165 00000 n
+0000000408 00000 n
+0000000649 00000 n
+0000000890 00000 n
+0000001131 00000 n
+0000001372 00000 n
+0000001613 00000 n
+0000001854 00000 n
+0000002096 00000 n
+0000002338 00000 n
+0000002581 00000 n
+0000002813 00000 n
+0000002971 00000 n
+0000003214 00000 n
+0000003457 00000 n
+0000003700 00000 n
+0000003943 00000 n
+0000004198 00000 n
+0000004302 00000 n
+0000004322 00000 n
+0000004454 00000 n
+0000004558 00000 n
+0000004601 00000 n
+0000004705 00000 n
+0000004748 00000 n
+0000004852 00000 n
+0000004895 00000 n
+0000004999 00000 n
+0000005042 00000 n
+0000005146 00000 n
+0000005189 00000 n
+0000005293 00000 n
+0000005336 00000 n
+0000005440 00000 n
+0000005483 00000 n
+0000005587 00000 n
+0000005631 00000 n
+0000005736 00000 n
+0000005767 00000 n
+0000006011 00000 n
+0000006255 00000 n
+0000006499 00000 n
+0000006743 00000 n
+0000007000 00000 n
+0000007105 00000 n
+0000007149 00000 n
+0000007254 00000 n
+0000007298 00000 n
+0000007403 00000 n
+0000007447 00000 n
+0000007552 00000 n
+0000007596 00000 n
+0000007701 00000 n
+0000007745 00000 n
+0000007850 00000 n
+0000007894 00000 n
+0000007999 00000 n
+0000008043 00000 n
+0000008148 00000 n
+0000008192 00000 n
+0000008297 00000 n
+0000008341 00000 n
+0000008446 00000 n
+trailer <<
+ /Info 2 0 R
+ /Root 1 0 R
+ /Size 66
+ /ID [<e032a88c7a987db6ca3abee555506ccc><31415926535897932384626433832795>]
+>>
+startxref
+8466
+%%EOF