[poppler] poppler/Annot.cc poppler/Annot.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Sep 27 12:02:23 UTC 2018


 poppler/Annot.cc |   66 +++++++++++++++++++++++++++++++++++++++++++++----------
 poppler/Annot.h  |    2 +
 2 files changed, 57 insertions(+), 11 deletions(-)

New commits:
commit f3e3dd8004d87468d0e07c3fe6c05cc0fab50a52
Author: Oliver Sander <oliver.sander at tu-dresden.de>
Date:   Thu Sep 27 13:58:34 2018 +0200

    FreeText: Use font from default appearance string
    
    If a FreeText annotation misses an AP entry, try to create a temporary font
    as defined by its default appearance string. Tf operator names the font resource,
    and we can search for the resource inside the default resource dictionary.
    See ISO32000 sections about "Free Text Annotations" and "Variable Text".
    
    If lookup fails for some reason, use Helvetica as fallback.
    
    Patch done together with Tobias Deiminger

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 238dbe94..75320836 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -41,6 +41,7 @@
 // Copyright (C) 2018 Adam Reichold <adam.reichold at t-online.de>
 // Copyright (C) 2018 Dileep Sankhla <sankhla.dileep96 at gmail.com>
 // Copyright (C) 2018 Tobias Deiminger <haxtibal at posteo.de>
+// Copyright (C) Oliver Sander <oliver.sander at tu-dresden.de>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -1781,6 +1782,10 @@ void AnnotAppearanceBuilder::drawCircleBottomRight(double cx, double cy, double
 }
 
 Object Annot::createForm(const GooString *appearBuf, double *bbox, GBool transparencyGroup, Dict *resDict) {
+  return createForm(appearBuf, bbox, transparencyGroup, resDict ? Object(resDict) : Object());
+}
+
+Object Annot::createForm(const GooString *appearBuf, double *bbox, GBool transparencyGroup, Object &&resDictObject) {
   Dict *appearDict = new Dict(xref);
   appearDict->set("Length", Object(appearBuf->getLength()));
   appearDict->set("Subtype", Object(objName, "Form"));
@@ -1796,8 +1801,8 @@ Object Annot::createForm(const GooString *appearBuf, double *bbox, GBool transpa
     d->set("S", Object(objName, "Transparency"));
     appearDict->set("Group", Object(d));
   }
-  if (resDict)
-    appearDict->set("Resources", Object(resDict));
+  if (resDictObject.isDict())
+    appearDict->set("Resources", std::move(resDictObject));
 
   Stream *mStream = new AutoFreeMemStream(copyString(appearBuf->getCString()), 0,
 				     appearBuf->getLength(), Object(appearDict));
@@ -2856,21 +2861,21 @@ std::unique_ptr<DefaultAppearance> AnnotFreeText::getDefaultAppearance() const {
   return std::make_unique<DefaultAppearance>(appearanceString);
 }
 
-static GfxFont *createAnnotDrawFont(XRef * xref, Dict *fontResDict)
+static GfxFont * createAnnotDrawFont(XRef * xref, Dict *fontResDict, const char* resourceName = "AnnotDrawFont", const char* fontname = "Helvetica")
 {
   const Ref dummyRef = { -1, -1 };
 
   Dict *fontDict = new Dict(xref);
-  fontDict->add("BaseFont", Object(objName, "Helvetica"));
+  fontDict->add("BaseFont", Object(objName, fontname));
   fontDict->add("Subtype", Object(objName, "Type0"));
   fontDict->add("Encoding", Object(objName, "WinAnsiEncoding"));
 
   Dict *fontsDict = new Dict(xref);
-  fontsDict->add("AnnotDrawFont", Object(fontDict));
+  fontsDict->add(resourceName, Object(fontDict));
 
   fontResDict->add("Font", Object(fontsDict));
 
-  return GfxFont::makeFont(xref, "AnnotDrawFont", dummyRef, fontDict);
+  return GfxFont::makeFont(xref, resourceName, dummyRef, fontDict);
 }
 
 void AnnotFreeText::generateFreeTextAppearance()
@@ -2892,6 +2897,8 @@ void AnnotFreeText::generateFreeTextAppearance()
   DefaultAppearance da{appearanceString};
 
   // Default values
+  if (!da.getFontName().isName())
+    da.setFontName(Object(objName, "AnnotDrawFont"));
   if (da.getFontPtSize() <= 0)
     da.setFontPtSize(10);
   if (!da.getFontColor())
@@ -2920,13 +2927,50 @@ void AnnotFreeText::generateFreeTextAppearance()
   const double textwidth = width - 2*textmargin;
   appearBuilder.appendf ("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n", textmargin, textwidth, height - 2*textmargin);
 
-  Dict *fontResDict = new Dict(xref);
-  GfxFont *font = createAnnotDrawFont(xref, fontResDict);
+  GfxFont *font = nullptr;
+
+  // look for font name in default resources
+  Form *form = doc->getCatalog()->getForm(); // form is owned by catalog, no need to clean it up
+
+  Object resourceObj;
+  if (form && form->getDefaultResourcesObj() && form->getDefaultResourcesObj()->isDict()) {
+    resourceObj = form->getDefaultResourcesObj()->copy(); // No real copy, but increment refcount of /DR Dict
+
+    Dict *resDict = resourceObj.getDict();
+    Object fontResources = resDict->lookup("Font");  // The 'Font' subdictionary
+
+    if (!fontResources.isDict()) {
+      error(errSyntaxWarning, -1, "Font subdictionary is not a dictionary");
+    } else {
+      // Get the font dictionary for the actual requested font
+      Object fontDictionary = fontResources.getDict()->lookupNF(da.getFontName().getName());
+
+      // Resolve reference, if necessary
+      Ref fontReference = {-1, -1};
+      if (fontDictionary.isRef()) {
+        fontReference = fontDictionary.getRef();
+        fontDictionary = fontDictionary.fetch(xref);
+      }
+
+      if (fontDictionary.isDict()) {
+        font = GfxFont::makeFont(xref, da.getFontName().getName(), fontReference, fontDictionary.getDict());
+      } else {
+        error(errSyntaxWarning, -1, "Font dictionary is not a dictionary");
+      }
+    }
+  }
+
+  // if fontname is not in in default resources, create a Helvetica fake font
+  if (!font) {
+    Dict *fontResDict = new Dict(xref);
+    resourceObj = Object(fontResDict);
+    font = createAnnotDrawFont(xref, fontResDict, da.getFontName().getName());
+  }
 
   // Set font state
   appearBuilder.setDrawColor(da.getFontColor(), gTrue);
   appearBuilder.appendf ("BT 1 0 0 1 {0:.2f} {1:.2f} Tm\n", textmargin, height - textmargin - da.getFontPtSize() * font->getDescent());
-  appearBuilder.appendf ("/AnnotDrawFont {0:.2f} Tf\n", da.getFontPtSize());
+  appearBuilder.setTextFont(da.getFontName(), da.getFontPtSize());
 
   int i = 0;
   double xposPrev = 0;
@@ -2961,9 +3005,9 @@ void AnnotFreeText::generateFreeTextAppearance()
   bbox[3] = rect->y2 - rect->y1;
 
   if (ca == 1) {
-    appearance = createForm(appearBuilder.buffer(), bbox, gFalse, fontResDict);
+    appearance = createForm(appearBuilder.buffer(), bbox, gFalse, std::move(resourceObj));
   } else {
-    Object aStream = createForm(appearBuilder.buffer(), bbox, gTrue, fontResDict);
+    Object aStream = createForm(appearBuilder.buffer(), bbox, gTrue, std::move(resourceObj));
 
     GooString appearBuf("/GS0 gs\n/Fm0 Do");
     Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr);
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 5b04e982..e4c5d65b 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -29,6 +29,7 @@
 // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info at kdab.com>. Work sponsored by the LiMux project of the city of Munich
 // Copyright (C) 2018 Dileep Sankhla <sankhla.dileep96 at gmail.com>
 // Copyright (C) 2018 Tobias Deiminger <haxtibal at posteo.de>
+// Copyright (C) Oliver Sander <oliver.sander at tu-dresden.de>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -727,6 +728,7 @@ protected:
   virtual ~Annot();
   virtual void removeReferencedObjects(); // Called by Page::removeAnnot
   Object createForm(const GooString *appearBuf, double *bbox, GBool transparencyGroup, Dict *resDict);
+  Object createForm(const GooString *appearBuf, double *bbox, GBool transparencyGroup, Object &&resDictObject); // overload to support incRef/decRef
   Dict *createResourcesDict(const char *formName, Object &&formStream, const char *stateName,
 			   double opacity, const char *blendMode);
   GBool isVisible(GBool printing);


More information about the poppler mailing list