2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 10:58:58 +00:00

Allow --rotate=0

This commit is contained in:
Jay Berkenbilt 2021-02-20 16:28:58 -05:00
parent 71e8627285
commit 35dd11f356
6 changed files with 952 additions and 6 deletions

View File

@ -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> 2021-02-18 Jay Berkenbilt <ejb@ql.org>
* Add QPDFAcroFormDocumentHelper::addFormField, which adds a new * Add QPDFAcroFormDocumentHelper::addFormField, which adds a new

View File

@ -1579,6 +1579,8 @@ QPDFObjectHandle::rotatePage(int angle, bool relative)
new_angle += old_angle; new_angle += old_angle;
} }
new_angle = (new_angle + 360) % 360; 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)); replaceKey("/Rotate", QPDFObjectHandle::newInteger(new_angle));
} }

View File

@ -1008,7 +1008,7 @@ make
linkend="ref.page-selection"/>. If the page range is omitted, linkend="ref.page-selection"/>. If the page range is omitted,
the rotation is applied to all pages. The the rotation is applied to all pages. The
<option>angle</option> portion of the parameter may be either <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 <option>-</option>, the angle is added to or subtracted from
the specified pages' original rotations. This is almost always the specified pages' original rotations. This is almost always
what you want. Otherwise the pages' rotations are set to the what you want. Otherwise the pages' rotations are set to the
@ -5175,6 +5175,12 @@ print "\n";
from the given files. from the given files.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
It is now valid to provide <option>--rotate=0</option> to
clear rotation from a page.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</listitem> </listitem>
<listitem> <listitem>

View File

@ -1374,8 +1374,8 @@ ArgParser::argHelp()
<< " concatenated\n" << " concatenated\n"
<< "--flatten-rotation move page rotation from /Rotate key to content\n" << "--flatten-rotation move page rotation from /Rotate key to content\n"
<< "--rotate=[+|-]angle[:page-range]\n" << "--rotate=[+|-]angle[:page-range]\n"
<< " rotate each specified page 90, 180, or 270 degrees;\n" << " rotate each specified page 0, 90, 180, or 270\n"
<< " rotate all pages if no page range is given\n" << " degrees; rotate all pages if no page range is given\n"
<< "--split-pages=[n] write each output page to a separate file\n" << "--split-pages=[n] write each output page to a separate file\n"
<< "--overlay options -- overlay pages from another file\n" << "--overlay options -- overlay pages from another file\n"
<< "--underlay options -- underlay 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" << "or investigatory purposes. See manual for further discussion.\n"
<< "\n" << "\n"
<< "The --rotate flag can be used to specify pages to rotate pages either\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" << "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" << "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" << "it is added to or subtracted from the original rotation. Otherwise, the\n"
@ -3448,7 +3448,8 @@ ArgParser::parseRotationParameter(std::string const& parameter)
// ignore // ignore
} }
if (range_valid && 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()); int angle = QUtil::string_to_int(angle_str.c_str());
if (relative == -1) if (relative == -1)

View File

@ -2241,7 +2241,7 @@ $td->runtest("explicit keep files open = n",
show_ntests(); show_ntests();
# ---------- # ----------
$td->notify("--- Rotate Pages ---"); $td->notify("--- Rotate Pages ---");
$n_tests += 4; $n_tests += 6;
# Do absolute, positive, and negative on ranges that include # Do absolute, positive, and negative on ranges that include
# inherited and non-inherited. # inherited and non-inherited.
# Pages 11-15 inherit /Rotate 90 # Pages 11-15 inherit /Rotate 90
@ -2258,6 +2258,14 @@ $td->runtest("check output",
{$td->FILE => "a.pdf"}, {$td->FILE => "a.pdf"},
{$td->FILE => "rotated.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->runtest("rotate all pages",
{$td->COMMAND => {$td->COMMAND =>
"qpdf --static-id --rotate=180 minimal.pdf a.pdf"}, "qpdf --static-id --rotate=180 minimal.pdf a.pdf"},

View File

@ -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