Commit 962288647aec7a08b619e57b686ec2bb43a1059d

Authored by m-holger
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.
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