Commit 2d32f4db8fd125f2481ecf767d9f6506e80481f6

Authored by Jay Berkenbilt
1 parent 9cb59987

Handle fallback font size in text appearances

If we end up using our fallback font size when generating appearances
for text fields, reflect that in the Tf operator used in the
appearance stream.
ChangeLog
1 2019-01-20 Jay Berkenbilt <ejb@ql.org> 1 2019-01-20 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Tweak the content code generated for variable text fields to
  4 + better handle font sizes and multi-line text.
  5 +
3 * When generating appearance streams for variable text 6 * When generating appearance streams for variable text
4 annotations, properly handle the cases of there being no 7 annotations, properly handle the cases of there being no
5 appearance dictionary, no appearance stream, or an appearance 8 appearance dictionary, no appearance stream, or an appearance
libqpdf/QPDFFormFieldObjectHelper.cc
@@ -715,17 +715,23 @@ class TfFinder: public QPDFObjectHandle::TokenFilter @@ -715,17 +715,23 @@ class TfFinder: public QPDFObjectHandle::TokenFilter
715 virtual void handleToken(QPDFTokenizer::Token const&); 715 virtual void handleToken(QPDFTokenizer::Token const&);
716 double getTf(); 716 double getTf();
717 std::string getFontName(); 717 std::string getFontName();
  718 + std::string getDA();
718 719
719 private: 720 private:
720 double tf; 721 double tf;
  722 + size_t tf_idx;
721 std::string font_name; 723 std::string font_name;
722 double last_num; 724 double last_num;
  725 + size_t last_num_idx;
723 std::string last_name; 726 std::string last_name;
  727 + std::vector<std::string> DA;
724 }; 728 };
725 729
726 TfFinder::TfFinder() : 730 TfFinder::TfFinder() :
727 tf(11.0), 731 tf(11.0),
728 - last_num(0.0) 732 + tf_idx(0),
  733 + last_num(0.0),
  734 + last_num_idx(0)
729 { 735 {
730 } 736 }
731 737
@@ -734,11 +740,13 @@ TfFinder::handleToken(QPDFTokenizer::Token const&amp; token) @@ -734,11 +740,13 @@ TfFinder::handleToken(QPDFTokenizer::Token const&amp; token)
734 { 740 {
735 QPDFTokenizer::token_type_e ttype = token.getType(); 741 QPDFTokenizer::token_type_e ttype = token.getType();
736 std::string value = token.getValue(); 742 std::string value = token.getValue();
  743 + DA.push_back(token.getRawValue());
737 switch (ttype) 744 switch (ttype)
738 { 745 {
739 case QPDFTokenizer::tt_integer: 746 case QPDFTokenizer::tt_integer:
740 case QPDFTokenizer::tt_real: 747 case QPDFTokenizer::tt_real:
741 last_num = strtod(value.c_str(), 0); 748 last_num = strtod(value.c_str(), 0);
  749 + last_num_idx = DA.size() - 1;
742 break; 750 break;
743 751
744 case QPDFTokenizer::tt_name: 752 case QPDFTokenizer::tt_name:
@@ -754,6 +762,7 @@ TfFinder::handleToken(QPDFTokenizer::Token const&amp; token) @@ -754,6 +762,7 @@ TfFinder::handleToken(QPDFTokenizer::Token const&amp; token)
754 // insane things or suffering from over/underflow 762 // insane things or suffering from over/underflow
755 tf = last_num; 763 tf = last_num;
756 } 764 }
  765 + tf_idx = last_num_idx;
757 font_name = last_name; 766 font_name = last_name;
758 break; 767 break;
759 768
@@ -769,6 +778,30 @@ TfFinder::getTf() @@ -769,6 +778,30 @@ TfFinder::getTf()
769 } 778 }
770 779
771 std::string 780 std::string
  781 +TfFinder::getDA()
  782 +{
  783 + std::string result;
  784 + size_t n = this->DA.size();
  785 + for (size_t i = 0; i < n; ++i)
  786 + {
  787 + std::string cur = this->DA.at(i);
  788 + if (i == tf_idx)
  789 + {
  790 + double delta = strtod(cur.c_str(), 0) - this->tf;
  791 + if ((delta > 0.001) || (delta < -0.001))
  792 + {
  793 + // tf doesn't match the font size passed to Tf, so
  794 + // substitute.
  795 + QTC::TC("qpdf", "QPDFFormFieldObjectHelper fallback Tf");
  796 + cur = QUtil::double_to_string(tf);
  797 + }
  798 + }
  799 + result += cur;
  800 + }
  801 + return result;
  802 +}
  803 +
  804 +std::string
772 TfFinder::getFontName() 805 TfFinder::getFontName()
773 { 806 {
774 return this->font_name; 807 return this->font_name;
@@ -843,6 +876,7 @@ QPDFFormFieldObjectHelper::generateTextAppearance( @@ -843,6 +876,7 @@ QPDFFormFieldObjectHelper::generateTextAppearance(
843 tok.write(QUtil::unsigned_char_pointer(DA.c_str()), DA.length()); 876 tok.write(QUtil::unsigned_char_pointer(DA.c_str()), DA.length());
844 tok.finish(); 877 tok.finish();
845 double tf = tff.getTf(); 878 double tf = tff.getTf();
  879 + DA = tff.getDA();
846 880
847 std::string (*encoder)(std::string const&, char) = &QUtil::utf8_to_ascii; 881 std::string (*encoder)(std::string const&, char) = &QUtil::utf8_to_ascii;
848 std::string font_name = tff.getFontName(); 882 std::string font_name = tff.getFontName();
qpdf/qpdf.testcov
@@ -425,3 +425,4 @@ QPDFPageDocumentHelper ignore annotation with no appearance 0 @@ -425,3 +425,4 @@ QPDFPageDocumentHelper ignore annotation with no appearance 0
425 QPDFFormFieldObjectHelper create AS from scratch 0 425 QPDFFormFieldObjectHelper create AS from scratch 0
426 QPDFFormFieldObjectHelper create AP from scratch 0 426 QPDFFormFieldObjectHelper create AP from scratch 0
427 QPDFFormFieldObjectHelper replaced BMC at EOF 0 427 QPDFFormFieldObjectHelper replaced BMC at EOF 0
  428 +QPDFFormFieldObjectHelper fallback Tf 0
qpdf/qtest/qpdf/appearances-a-more2.pdf
No preview for this file type
qpdf/qtest/qpdf/need-appearances-more2.pdf
No preview for this file type