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 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 6 * When generating appearance streams for variable text
4 7 annotations, properly handle the cases of there being no
5 8 appearance dictionary, no appearance stream, or an appearance
... ...
libqpdf/QPDFFormFieldObjectHelper.cc
... ... @@ -715,17 +715,23 @@ class TfFinder: public QPDFObjectHandle::TokenFilter
715 715 virtual void handleToken(QPDFTokenizer::Token const&);
716 716 double getTf();
717 717 std::string getFontName();
  718 + std::string getDA();
718 719  
719 720 private:
720 721 double tf;
  722 + size_t tf_idx;
721 723 std::string font_name;
722 724 double last_num;
  725 + size_t last_num_idx;
723 726 std::string last_name;
  727 + std::vector<std::string> DA;
724 728 };
725 729  
726 730 TfFinder::TfFinder() :
727 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 740 {
735 741 QPDFTokenizer::token_type_e ttype = token.getType();
736 742 std::string value = token.getValue();
  743 + DA.push_back(token.getRawValue());
737 744 switch (ttype)
738 745 {
739 746 case QPDFTokenizer::tt_integer:
740 747 case QPDFTokenizer::tt_real:
741 748 last_num = strtod(value.c_str(), 0);
  749 + last_num_idx = DA.size() - 1;
742 750 break;
743 751  
744 752 case QPDFTokenizer::tt_name:
... ... @@ -754,6 +762,7 @@ TfFinder::handleToken(QPDFTokenizer::Token const&amp; token)
754 762 // insane things or suffering from over/underflow
755 763 tf = last_num;
756 764 }
  765 + tf_idx = last_num_idx;
757 766 font_name = last_name;
758 767 break;
759 768  
... ... @@ -769,6 +778,30 @@ TfFinder::getTf()
769 778 }
770 779  
771 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 805 TfFinder::getFontName()
773 806 {
774 807 return this->font_name;
... ... @@ -843,6 +876,7 @@ QPDFFormFieldObjectHelper::generateTextAppearance(
843 876 tok.write(QUtil::unsigned_char_pointer(DA.c_str()), DA.length());
844 877 tok.finish();
845 878 double tf = tff.getTf();
  879 + DA = tff.getDA();
846 880  
847 881 std::string (*encoder)(std::string const&, char) = &QUtil::utf8_to_ascii;
848 882 std::string font_name = tff.getFontName();
... ...
qpdf/qpdf.testcov
... ... @@ -425,3 +425,4 @@ QPDFPageDocumentHelper ignore annotation with no appearance 0
425 425 QPDFFormFieldObjectHelper create AS from scratch 0
426 426 QPDFFormFieldObjectHelper create AP from scratch 0
427 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