Commit 4cded10821e3bd523cf96eb628d7364820a07b84
1 parent
078cf9bf
Add QPDFObjectHandle::Rectangle type
Provide a convenient way of accessing rectangles.
Showing
4 changed files
with
127 additions
and
2 deletions
ChangeLog
| 1 | +2018-06-19 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * New QPDFObject::Rectangle class will convert to and from arrays | |
| 4 | + of four numerical values. Rectangles are used in various places | |
| 5 | + within the PDF file format and are called out as a specific data | |
| 6 | + type in the PDF specification. | |
| 7 | + | |
| 1 | 8 | 2018-05-12 Jay Berkenbilt <ejb@ql.org> |
| 2 | 9 | |
| 3 | 10 | * In newline before endstream mode, an extra newline was not | ... | ... |
include/qpdf/QPDFObjectHandle.hh
| ... | ... | @@ -172,6 +172,31 @@ class QPDFObjectHandle |
| 172 | 172 | void terminateParsing(); |
| 173 | 173 | }; |
| 174 | 174 | |
| 175 | + // Convenience object for rectangles | |
| 176 | + class Rectangle | |
| 177 | + { | |
| 178 | + public: | |
| 179 | + Rectangle() : | |
| 180 | + llx(0.0), | |
| 181 | + lly(0.0), | |
| 182 | + urx(0.0), | |
| 183 | + ury(0.0) | |
| 184 | + { | |
| 185 | + } | |
| 186 | + Rectangle(double llx, double lly, | |
| 187 | + double urx, double ury) : | |
| 188 | + llx(llx), | |
| 189 | + lly(lly), | |
| 190 | + urx(urx), | |
| 191 | + ury(ury) | |
| 192 | + { | |
| 193 | + } | |
| 194 | + | |
| 195 | + double llx; | |
| 196 | + double lly; | |
| 197 | + double urx; | |
| 198 | + double ury; | |
| 199 | + }; | |
| 175 | 200 | |
| 176 | 201 | QPDF_DLL |
| 177 | 202 | QPDFObjectHandle(); |
| ... | ... | @@ -344,11 +369,18 @@ class QPDFObjectHandle |
| 344 | 369 | static QPDFObjectHandle newArray( |
| 345 | 370 | std::vector<QPDFObjectHandle> const& items); |
| 346 | 371 | QPDF_DLL |
| 372 | + static QPDFObjectHandle newArray(Rectangle const&); | |
| 373 | + QPDF_DLL | |
| 347 | 374 | static QPDFObjectHandle newDictionary(); |
| 348 | 375 | QPDF_DLL |
| 349 | 376 | static QPDFObjectHandle newDictionary( |
| 350 | 377 | std::map<std::string, QPDFObjectHandle> const& items); |
| 351 | 378 | |
| 379 | + // Create an array from a rectangle. Equivalent to the rectangle | |
| 380 | + // form of newArray. | |
| 381 | + QPDF_DLL | |
| 382 | + static QPDFObjectHandle newFromRectangle(Rectangle const&); | |
| 383 | + | |
| 352 | 384 | // Create a new stream and associate it with the given qpdf |
| 353 | 385 | // object. A subsequent call must be made to replaceStreamData() |
| 354 | 386 | // to provide data for the stream. The stream's dictionary may be |
| ... | ... | @@ -465,6 +497,12 @@ class QPDFObjectHandle |
| 465 | 497 | QPDFObjectHandle getArrayItem(int n); |
| 466 | 498 | QPDF_DLL |
| 467 | 499 | std::vector<QPDFObjectHandle> getArrayAsVector(); |
| 500 | + QPDF_DLL | |
| 501 | + bool isRectangle(); | |
| 502 | + // If the array an array of four numeric values, return as a | |
| 503 | + // rectangle. Otherwise, return the rectangle [0, 0, 0, 0] | |
| 504 | + QPDF_DLL | |
| 505 | + Rectangle getArrayAsRectangle(); | |
| 468 | 506 | |
| 469 | 507 | // Methods for dictionary objects |
| 470 | 508 | QPDF_DLL |
| ... | ... | @@ -739,6 +777,15 @@ class QPDFObjectHandle |
| 739 | 777 | QPDF_DLL |
| 740 | 778 | void coalesceContentStreams(); |
| 741 | 779 | |
| 780 | + // Issue a warning about this object if possible. If the object | |
| 781 | + // has a description, a warning will be issued. Otherwise, if | |
| 782 | + // throw_if_no_description is true, throw an exception. Otherwise | |
| 783 | + // do nothing. Objects read normally from the file have | |
| 784 | + // descriptions. See comments on setObjectDescription for | |
| 785 | + // additional details. | |
| 786 | + void warnIfPossible(std::string const& warning, | |
| 787 | + bool throw_if_no_description = false); | |
| 788 | + | |
| 742 | 789 | // Initializers for objects. This Factory class gives the QPDF |
| 743 | 790 | // class specific permission to call factory methods without |
| 744 | 791 | // making it a friend of the whole QPDFObjectHandle class. | ... | ... |
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -554,6 +554,42 @@ QPDFObjectHandle::getArrayItem(int n) |
| 554 | 554 | return result; |
| 555 | 555 | } |
| 556 | 556 | |
| 557 | +bool | |
| 558 | +QPDFObjectHandle::isRectangle() | |
| 559 | +{ | |
| 560 | + if (! isArray()) | |
| 561 | + { | |
| 562 | + return false; | |
| 563 | + } | |
| 564 | + if (getArrayNItems() != 4) | |
| 565 | + { | |
| 566 | + return false; | |
| 567 | + } | |
| 568 | + for (size_t i = 0; i < 4; ++i) | |
| 569 | + { | |
| 570 | + if (! getArrayItem(i).isNumber()) | |
| 571 | + { | |
| 572 | + return false; | |
| 573 | + } | |
| 574 | + } | |
| 575 | + return true; | |
| 576 | +} | |
| 577 | + | |
| 578 | + | |
| 579 | +QPDFObjectHandle::Rectangle | |
| 580 | +QPDFObjectHandle::getArrayAsRectangle() | |
| 581 | +{ | |
| 582 | + Rectangle result; | |
| 583 | + if (isRectangle()) | |
| 584 | + { | |
| 585 | + result = Rectangle(getArrayItem(0).getNumericValue(), | |
| 586 | + getArrayItem(1).getNumericValue(), | |
| 587 | + getArrayItem(2).getNumericValue(), | |
| 588 | + getArrayItem(3).getNumericValue()); | |
| 589 | + } | |
| 590 | + return result; | |
| 591 | +} | |
| 592 | + | |
| 557 | 593 | std::vector<QPDFObjectHandle> |
| 558 | 594 | QPDFObjectHandle::getArrayAsVector() |
| 559 | 595 | { |
| ... | ... | @@ -1834,6 +1870,23 @@ QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items) |
| 1834 | 1870 | } |
| 1835 | 1871 | |
| 1836 | 1872 | QPDFObjectHandle |
| 1873 | +QPDFObjectHandle::newArray(Rectangle const& rect) | |
| 1874 | +{ | |
| 1875 | + std::vector<QPDFObjectHandle> items; | |
| 1876 | + items.push_back(newReal(rect.llx)); | |
| 1877 | + items.push_back(newReal(rect.lly)); | |
| 1878 | + items.push_back(newReal(rect.urx)); | |
| 1879 | + items.push_back(newReal(rect.ury)); | |
| 1880 | + return newArray(items); | |
| 1881 | +} | |
| 1882 | + | |
| 1883 | +QPDFObjectHandle | |
| 1884 | +QPDFObjectHandle::newFromRectangle(Rectangle const& rect) | |
| 1885 | +{ | |
| 1886 | + return newArray(rect); | |
| 1887 | +} | |
| 1888 | + | |
| 1889 | +QPDFObjectHandle | |
| 1837 | 1890 | QPDFObjectHandle::newDictionary() |
| 1838 | 1891 | { |
| 1839 | 1892 | return newDictionary(std::map<std::string, QPDFObjectHandle>()); |
| ... | ... | @@ -2103,7 +2156,8 @@ QPDFObjectHandle::typeWarning(char const* expected_type, |
| 2103 | 2156 | } |
| 2104 | 2157 | |
| 2105 | 2158 | void |
| 2106 | -QPDFObjectHandle::objectWarning(std::string const& warning) | |
| 2159 | +QPDFObjectHandle::warnIfPossible(std::string const& warning, | |
| 2160 | + bool throw_if_no_description) | |
| 2107 | 2161 | { |
| 2108 | 2162 | QPDF* context = 0; |
| 2109 | 2163 | std::string description; |
| ... | ... | @@ -2115,13 +2169,19 @@ QPDFObjectHandle::objectWarning(std::string const& warning) |
| 2115 | 2169 | "", description, 0, |
| 2116 | 2170 | warning)); |
| 2117 | 2171 | } |
| 2118 | - else | |
| 2172 | + else if (throw_if_no_description) | |
| 2119 | 2173 | { |
| 2120 | 2174 | throw std::logic_error(warning); |
| 2121 | 2175 | } |
| 2122 | 2176 | } |
| 2123 | 2177 | |
| 2124 | 2178 | void |
| 2179 | +QPDFObjectHandle::objectWarning(std::string const& warning) | |
| 2180 | +{ | |
| 2181 | + warnIfPossible(warning, true); | |
| 2182 | +} | |
| 2183 | + | |
| 2184 | +void | |
| 2125 | 2185 | QPDFObjectHandle::assertType(char const* type_name, bool istype) |
| 2126 | 2186 | { |
| 2127 | 2187 | if (! istype) | ... | ... |
qpdf/test_driver.cc
| ... | ... | @@ -1449,6 +1449,17 @@ void runtest(int n, char const* filename1, char const* arg2) |
| 1449 | 1449 | QPDFObjectHandle page = pdf.getAllPages()[0]; |
| 1450 | 1450 | assert("/QPDFFakeName" == |
| 1451 | 1451 | page.getKey("/Contents").getDict().getKey("/Potato").getName()); |
| 1452 | + // Rectangles | |
| 1453 | + QPDFObjectHandle::Rectangle r0 = integer.getArrayAsRectangle(); | |
| 1454 | + assert((r0.llx == 0) && (r0.lly == 0) && | |
| 1455 | + (r0.urx == 0) && (r0.ury == 0)); | |
| 1456 | + QPDFObjectHandle rect = QPDFObjectHandle::newFromRectangle( | |
| 1457 | + QPDFObjectHandle::Rectangle(1.2, 3.4, 5.6, 7.8)); | |
| 1458 | + QPDFObjectHandle::Rectangle r1 = rect.getArrayAsRectangle(); | |
| 1459 | + assert((r1.llx > 1.19) && (r1.llx < 1.21) && | |
| 1460 | + (r1.lly > 3.39) && (r1.lly < 3.41) && | |
| 1461 | + (r1.urx > 5.59) && (r1.urx < 5.61) && | |
| 1462 | + (r1.ury > 7.79) && (r1.ury < 7.81)); | |
| 1452 | 1463 | } |
| 1453 | 1464 | else |
| 1454 | 1465 | { | ... | ... |