Commit 962288647aec7a08b619e57b686ec2bb43a1059d
1 parent
1527bf29
Refactor stream filtering to simplify decode-level handling.
Replaced individual compression flags with a unified decode-level parameter for stream filtering. Introduced a helper function to handle filtering conditions, reducing redundancy and improving readability. Removed unused code and updated related tests to reflect these changes.
Showing
3 changed files
with
18 additions
and
41 deletions
libqpdf/QPDF_Stream.cc
| @@ -343,9 +343,8 @@ Stream::isRootMetadata() const | @@ -343,9 +343,8 @@ Stream::isRootMetadata() const | ||
| 343 | 343 | ||
| 344 | bool | 344 | bool |
| 345 | Stream::filterable( | 345 | Stream::filterable( |
| 346 | - std::vector<std::shared_ptr<QPDFStreamFilter>>& filters, | ||
| 347 | - bool& specialized_compression, | ||
| 348 | - bool& lossy_compression) | 346 | + qpdf_stream_decode_level_e decode_level, |
| 347 | + std::vector<std::shared_ptr<QPDFStreamFilter>>& filters) | ||
| 349 | { | 348 | { |
| 350 | auto s = stream(); | 349 | auto s = stream(); |
| 351 | // Check filters | 350 | // Check filters |
| @@ -387,6 +386,16 @@ Stream::filterable( | @@ -387,6 +386,16 @@ Stream::filterable( | ||
| 387 | 386 | ||
| 388 | auto decode_obj = s->stream_dict.getKey("/DecodeParms"); | 387 | auto decode_obj = s->stream_dict.getKey("/DecodeParms"); |
| 389 | 388 | ||
| 389 | + auto can_filter = // linebreak | ||
| 390 | + [](auto d_level, auto& filter, auto& d_obj) -> bool { | ||
| 391 | + if (!filter.setDecodeParms(d_obj) || | ||
| 392 | + (d_level < qpdf_dl_all && filter.isLossyCompression()) || | ||
| 393 | + (d_level < qpdf_dl_specialized && filter.isSpecializedCompression())) { | ||
| 394 | + return false; | ||
| 395 | + } | ||
| 396 | + return true; | ||
| 397 | + }; | ||
| 398 | + | ||
| 390 | auto decode_array = decode_obj.as_array(strict); | 399 | auto decode_array = decode_obj.as_array(strict); |
| 391 | if (!decode_array || decode_array.size() == 0) { | 400 | if (!decode_array || decode_array.size() == 0) { |
| 392 | if (decode_array) { | 401 | if (decode_array) { |
| @@ -394,17 +403,9 @@ Stream::filterable( | @@ -394,17 +403,9 @@ Stream::filterable( | ||
| 394 | } | 403 | } |
| 395 | 404 | ||
| 396 | for (auto& filter: filters) { | 405 | for (auto& filter: filters) { |
| 397 | - if (!filter->setDecodeParms(decode_obj)) { | 406 | + if (!can_filter(decode_level, *filter, decode_obj)) { |
| 398 | return false; | 407 | return false; |
| 399 | } | 408 | } |
| 400 | - if (filter->isLossyCompression()) { | ||
| 401 | - specialized_compression = true; | ||
| 402 | - lossy_compression = true; | ||
| 403 | - continue; | ||
| 404 | - } | ||
| 405 | - if (filter->isSpecializedCompression()) { | ||
| 406 | - specialized_compression = true; | ||
| 407 | - } | ||
| 408 | } | 409 | } |
| 409 | } else { | 410 | } else { |
| 410 | // Ignore /DecodeParms entirely if /Filters is empty. At least one case of a file whose | 411 | // Ignore /DecodeParms entirely if /Filters is empty. At least one case of a file whose |
| @@ -416,17 +417,10 @@ Stream::filterable( | @@ -416,17 +417,10 @@ Stream::filterable( | ||
| 416 | 417 | ||
| 417 | int i = -1; | 418 | int i = -1; |
| 418 | for (auto& filter: filters) { | 419 | for (auto& filter: filters) { |
| 419 | - if (!filter->setDecodeParms(decode_array.at(++i).second)) { | 420 | + auto d_obj = decode_array.at(++i).second; |
| 421 | + if (!can_filter(decode_level, *filter, d_obj)) { | ||
| 420 | return false; | 422 | return false; |
| 421 | } | 423 | } |
| 422 | - if (filter->isLossyCompression()) { | ||
| 423 | - specialized_compression = true; | ||
| 424 | - lossy_compression = true; | ||
| 425 | - continue; | ||
| 426 | - } | ||
| 427 | - if (filter->isSpecializedCompression()) { | ||
| 428 | - specialized_compression = true; | ||
| 429 | - } | ||
| 430 | } | 424 | } |
| 431 | } | 425 | } |
| 432 | 426 | ||
| @@ -444,8 +438,6 @@ Stream::pipeStreamData( | @@ -444,8 +438,6 @@ Stream::pipeStreamData( | ||
| 444 | { | 438 | { |
| 445 | auto s = stream(); | 439 | auto s = stream(); |
| 446 | std::vector<std::shared_ptr<QPDFStreamFilter>> filters; | 440 | std::vector<std::shared_ptr<QPDFStreamFilter>> filters; |
| 447 | - bool specialized_compression = false; | ||
| 448 | - bool lossy_compression = false; | ||
| 449 | bool ignored; | 441 | bool ignored; |
| 450 | if (!filterp) { | 442 | if (!filterp) { |
| 451 | filterp = &ignored; | 443 | filterp = &ignored; |
| @@ -453,20 +445,7 @@ Stream::pipeStreamData( | @@ -453,20 +445,7 @@ Stream::pipeStreamData( | ||
| 453 | bool& filter = *filterp; | 445 | bool& filter = *filterp; |
| 454 | filter = encode_flags || decode_level != qpdf_dl_none; | 446 | filter = encode_flags || decode_level != qpdf_dl_none; |
| 455 | if (filter) { | 447 | if (filter) { |
| 456 | - filter = filterable(filters, specialized_compression, lossy_compression); | ||
| 457 | - if ((decode_level < qpdf_dl_all) && lossy_compression) { | ||
| 458 | - filter = false; | ||
| 459 | - } | ||
| 460 | - if (decode_level < qpdf_dl_specialized && specialized_compression) { | ||
| 461 | - filter = false; | ||
| 462 | - } | ||
| 463 | - QTC::TC( | ||
| 464 | - "qpdf", | ||
| 465 | - "QPDF_Stream special filters", | ||
| 466 | - (!filter) ? 0 | ||
| 467 | - : lossy_compression ? 1 | ||
| 468 | - : specialized_compression ? 2 | ||
| 469 | - : 3); | 448 | + filter = filterable(decode_level, filters); |
| 470 | } | 449 | } |
| 471 | 450 | ||
| 472 | if (!pipeline) { | 451 | if (!pipeline) { |
libqpdf/qpdf/QPDFObjectHandle_private.hh
| @@ -312,9 +312,8 @@ namespace qpdf | @@ -312,9 +312,8 @@ namespace qpdf | ||
| 312 | return nullptr; // unreachable | 312 | return nullptr; // unreachable |
| 313 | } | 313 | } |
| 314 | bool filterable( | 314 | bool filterable( |
| 315 | - std::vector<std::shared_ptr<QPDFStreamFilter>>& filters, | ||
| 316 | - bool& specialized_compression, | ||
| 317 | - bool& lossy_compression); | 315 | + qpdf_stream_decode_level_e decode_level, |
| 316 | + std::vector<std::shared_ptr<QPDFStreamFilter>>& filters); | ||
| 318 | void replaceFilterData( | 317 | void replaceFilterData( |
| 319 | QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms, size_t length); | 318 | QPDFObjectHandle const& filter, QPDFObjectHandle const& decode_parms, size_t length); |
| 320 | 319 |
qpdf/qpdf.testcov
| @@ -278,7 +278,6 @@ QPDF ignore second extra space in xref entry 0 | @@ -278,7 +278,6 @@ QPDF ignore second extra space in xref entry 0 | ||
| 278 | QPDF ignore length error xref entry 0 | 278 | QPDF ignore length error xref entry 0 |
| 279 | QPDF_encryption pad short parameter 0 | 279 | QPDF_encryption pad short parameter 0 |
| 280 | QPDFObjectHandle found old angle 1 | 280 | QPDFObjectHandle found old angle 1 |
| 281 | -QPDF_Stream special filters 3 | ||
| 282 | QPDFTokenizer block long token 0 | 281 | QPDFTokenizer block long token 0 |
| 283 | qpdf-c called qpdf_set_decode_level 0 | 282 | qpdf-c called qpdf_set_decode_level 0 |
| 284 | qpdf-c called qpdf_set_compress_streams 0 | 283 | qpdf-c called qpdf_set_compress_streams 0 |