[poppler] Branch 'poppler-0.10' - 6 commits - poppler/Annot.cc poppler/Annot.h poppler/Catalog.cc poppler/Gfx.cc poppler/Gfx.h poppler/OptionalContent.cc poppler/OptionalContent.h qt4/src qt4/tests

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Nov 9 11:56:52 PST 2008


 poppler/Annot.cc               |   20 ++++---
 poppler/Annot.h                |    4 -
 poppler/Catalog.cc             |    4 +
 poppler/Gfx.cc                 |  113 ++++++++++++++++++++++++++++-------------
 poppler/Gfx.h                  |    7 +-
 poppler/OptionalContent.cc     |   38 ++++++-------
 poppler/OptionalContent.h      |   23 +++++---
 qt4/src/poppler-optcontent.cc  |    6 +-
 qt4/tests/check_optcontent.cpp |    8 +-
 9 files changed, 141 insertions(+), 82 deletions(-)

New commits:
commit 9db1b1a4e4a58fc870368eab1e3755cdee8075fc
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Nov 9 17:03:20 2008 +0100

    Fix a crash when initializing an Annot with a null catalog
    
    Forms crate a temp annot just to get the font size of the form field
    passing a NULL catalog.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 76a7cb1..45d063d 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -958,7 +958,7 @@ void Annot::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
   }
   obj1.free();
 
-  optContentConfig = catalog->getOptContentConfig();
+  optContentConfig = catalog ? catalog->getOptContentConfig() : NULL;
   dict->lookupNF("OC", &oc);
   if (!oc.isRef() && !oc.isNull()) {
     error (-1, "Annotation OC value not null or dict: %i", oc.getType());
commit 70ada8a25a62e0b58d6db47c36b7ee32bbd9ddd7
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Oct 26 19:42:53 2008 +0100

    Fix memory leaks in OptionalContent

diff --git a/poppler/OptionalContent.cc b/poppler/OptionalContent.cc
index 4a3d4a9..f59b16a 100644
--- a/poppler/OptionalContent.cc
+++ b/poppler/OptionalContent.cc
@@ -28,7 +28,7 @@
 //------------------------------------------------------------------------
 
 OCGs::OCGs(Object *ocgObject, XRef *xref) :
-  m_orderArray(0), m_rBGroupsArray(), m_xref(xref)
+  m_xref(xref)
 {
   // we need to parse the dictionary here, and build optionalContentGroups
   ok = gTrue;
@@ -126,17 +126,8 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
   }
   off.free();
 
-  Object order;
   defaultOcgConfig.dictLookup("Order", &order);
-  if ( (order.isArray()) && (order.arrayGetLength() > 0) ) {
-    m_orderArray = order.getArray();
-  }
-
-  Object rbgroups;
   defaultOcgConfig.dictLookup("RBGroups", &rbgroups);
-  if ( (rbgroups.isArray()) && (rbgroups.arrayGetLength() > 0) ) {
-    m_rBGroupsArray = rbgroups.getArray();
-  }
 
   ocgList.free();
   defaultOcgConfig.free();
@@ -145,6 +136,8 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
 OCGs::~OCGs()
 {
   deleteGooList(optionalContentGroups, OptionalContentGroup);
+  order.free();
+  rbgroups.free();
 }
 
 
diff --git a/poppler/OptionalContent.h b/poppler/OptionalContent.h
index b6136c3..90fded2 100644
--- a/poppler/OptionalContent.h
+++ b/poppler/OptionalContent.h
@@ -40,8 +40,10 @@ public:
 
   OptionalContentGroup* findOcgByRef( const Ref &ref);
 
-  Array* getOrderArray() const { return m_orderArray; }
-  Array* getRBGroupsArray() const { return m_rBGroupsArray; }
+  Array* getOrderArray() 
+    { return (order.isArray() && order.arrayGetLength() > 0) ? order.getArray() : NULL; }
+  Array* getRBGroupsArray() 
+    { return (rbgroups.isArray() && rbgroups.arrayGetLength()) ? rbgroups.getArray() : NULL; }
 
   bool optContentIsVisible( Object *dictRef );
 
@@ -55,8 +57,8 @@ private:
 
   GooList *optionalContentGroups;
 
-  Array *m_orderArray;
-  Array *m_rBGroupsArray;
+  Object order;
+  Object rbgroups;
   XRef *m_xref;
 };
 
commit 8ee20b72cad944dea918365713f14a8d9fbf1ea0
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Oct 26 19:11:45 2008 +0100

    Check annotation optional content properties before drawing it

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 6e35b2a..76a7cb1 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -957,13 +957,12 @@ void Annot::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
     treeKey = 0;
   }
   obj1.free();
-  
-  if (dict->lookup("OC", &obj1)->isDict()) {
-    optionalContent = new OCGs(&obj1, xrefA);
-  } else {
-    optionalContent = NULL;
+
+  optContentConfig = catalog->getOptContentConfig();
+  dict->lookupNF("OC", &oc);
+  if (!oc.isRef() && !oc.isNull()) {
+    error (-1, "Annotation OC value not null or dict: %i", oc.getType());
   }
-  obj1.free();
 }
 
 double Annot::getXMin() {
@@ -1013,8 +1012,7 @@ Annot::~Annot() {
   if (color)
     delete color;
 
-  if (optionalContent)
-    delete optionalContent;
+  oc.free();
 }
 
 // Set the current fill or stroke color, based on <a> (which should
@@ -1149,6 +1147,12 @@ void Annot::draw(Gfx *gfx, GBool printing) {
     return;
   }
 
+  // check the OC
+  if (optContentConfig && oc.isRef()) {
+    if (! optContentConfig->optContentIsVisible(&oc))
+      return;
+  }
+
   // draw the appearance stream
   appearance.fetch(xref, &obj);
   gfx->drawAnnot(&obj, (type == typeLink) ? border : (AnnotBorder *)NULL, color,
diff --git a/poppler/Annot.h b/poppler/Annot.h
index ebd3e74..6dd7850 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -509,7 +509,6 @@ public:
   AnnotBorder *getBorder() const { return border; }
   AnnotColor *getColor() const { return color; }
   int getTreeKey() const { return treeKey; }
-  OCGs *getOptionalContent() const { return optionalContent; }
 
   int getId() { return ref.num; }
 
@@ -542,7 +541,8 @@ protected:
                          //   for the normal appearance
   GooString *appearState;           // AS
   int treeKey;                      // Struct Parent;
-  OCGs *optionalContent;            // OC
+  OCGs *optContentConfig;           // Optional content config
+  Object oc;                        // OC
 
   XRef *xref;			// the xref table for this PDF file
   Ref ref;                      // object ref identifying this annotation
commit 36e07afe3280e9f72ebc0c2b42faf694606575ab
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Nov 8 20:50:40 2008 +0100

    Do not show hidden optional content
    
    Before any draw operation we first check whether we are inside an
    optional marked content element that is currently hidden.

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index be2f19a..871feb3 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -496,6 +496,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, Catalog *cata
   subPage = gFalse;
   printCommands = globalParams->getPrintCommands();
   profileCommands = globalParams->getProfileCommands();
+  mcStack = NULL;
 
   // start the resource stack
   res = new GfxResources(xref, resDict, NULL);
@@ -539,6 +540,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, Catalog *catalogA,
   catalog = catalogA;
   subPage = gTrue;
   printCommands = globalParams->getPrintCommands();
+  mcStack = NULL;
 
   // start the resource stack
   res = new GfxResources(xref, resDict, NULL);
@@ -582,6 +584,9 @@ Gfx::~Gfx() {
   if (state) {
     delete state;
   }
+  while (mcStack) {
+    popMarkedContent();
+  }
 }
 
 void Gfx::display(Object *obj, GBool topLevel) {
@@ -1562,7 +1567,7 @@ void Gfx::opStroke(Object args[], int numArgs) {
     //error(getPos(), "No path in stroke");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     if (state->getStrokeColorSpace()->getMode() == csPattern) {
       doPatternStroke();
     } else {
@@ -1578,7 +1583,7 @@ void Gfx::opCloseStroke(Object * /*args[]*/, int /*numArgs*/) {
     return;
   }
   state->closePath();
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     if (state->getStrokeColorSpace()->getMode() == csPattern) {
       doPatternStroke();
     } else {
@@ -1593,7 +1598,7 @@ void Gfx::opFill(Object args[], int numArgs) {
     //error(getPos(), "No path in fill");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     if (state->getFillColorSpace()->getMode() == csPattern) {
       doPatternFill(gFalse);
     } else {
@@ -1608,7 +1613,7 @@ void Gfx::opEOFill(Object args[], int numArgs) {
     //error(getPos(), "No path in eofill");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     if (state->getFillColorSpace()->getMode() == csPattern) {
       doPatternFill(gTrue);
     } else {
@@ -1623,7 +1628,7 @@ void Gfx::opFillStroke(Object args[], int numArgs) {
     //error(getPos(), "No path in fill/stroke");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     if (state->getFillColorSpace()->getMode() == csPattern) {
       doPatternFill(gFalse);
     } else {
@@ -1643,7 +1648,7 @@ void Gfx::opCloseFillStroke(Object args[], int numArgs) {
     //error(getPos(), "No path in closepath/fill/stroke");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     state->closePath();
     if (state->getFillColorSpace()->getMode() == csPattern) {
       doPatternFill(gFalse);
@@ -1664,7 +1669,7 @@ void Gfx::opEOFillStroke(Object args[], int numArgs) {
     //error(getPos(), "No path in eofill/stroke");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     if (state->getFillColorSpace()->getMode() == csPattern) {
       doPatternFill(gTrue);
     } else {
@@ -1684,7 +1689,7 @@ void Gfx::opCloseEOFillStroke(Object args[], int numArgs) {
     //error(getPos(), "No path in closepath/eofill/stroke");
     return;
   }
-  if (state->isPath()) {
+  if (state->isPath() && !contentIsHidden()) {
     state->closePath();
     if (state->getFillColorSpace()->getMode() == csPattern) {
       doPatternFill(gTrue);
@@ -1911,10 +1916,12 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
   if (out->useTilingPatternFill()) {
     m1[4] = m[4];
     m1[5] = m[5];
-    out->tilingPatternFill(state, tPat->getContentStream(),
-			   tPat->getPaintType(), tPat->getResDict(),
-			   m1, tPat->getBBox(),
-			   xi0, yi0, xi1, yi1, xstep, ystep);
+    if (!contentIsHidden()) {
+      out->tilingPatternFill(state, tPat->getContentStream(),
+			     tPat->getPaintType(), tPat->getResDict(),
+			     m1, tPat->getBBox(),
+			     xi0, yi0, xi1, yi1, xstep, ystep);
+    }
   } else {
     for (yi = yi0; yi < yi1; ++yi) {
       for (xi = xi0; xi < xi1; ++xi) {
@@ -1983,7 +1990,8 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
   if (shading->getHasBackground()) {
     state->setFillColor(shading->getBackground());
     out->updateFillColor(state);
-    out->fill(state);
+    if (!contentIsHidden())
+      out->fill(state);
   }
   state->clearPath();
 
@@ -2196,7 +2204,8 @@ void Gfx::doFunctionShFill1(GfxFunctionShading *shading,
     state->lineTo(x0 * matrix[0] + y1 * matrix[2] + matrix[4],
 		  x0 * matrix[1] + y1 * matrix[3] + matrix[5]);
     state->closePath();
-    out->fill(state);
+    if (!contentIsHidden())
+      out->fill(state);
     state->clearPath();
 
   // the four corner colors are not close enough -- subdivide the
@@ -2485,7 +2494,8 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
     state->lineTo(vx1, vy1);
     state->lineTo(ux1, uy1);
     state->closePath();
-    out->fill(state);
+    if (!contentIsHidden())
+      out->fill(state);
     state->clearPath();
 
     // set up for next region
@@ -2761,7 +2771,8 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
     }
 
     // fill the path
-    out->fill(state);
+    if (!contentIsHidden())
+      out->fill(state);
     state->clearPath();
 
     // step to the next value of t
@@ -2798,7 +2809,8 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
 	state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
       }
       state->closePath();
-      out->fill(state);
+      if (!contentIsHidden())
+        out->fill(state);
       state->clearPath();
     }
 
@@ -2830,7 +2842,8 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
 	state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
       }
       state->closePath();
-      out->fill(state);
+      if (!contentIsHidden())
+        out->fill(state);
       state->clearPath();
     }
   }
@@ -2871,7 +2884,8 @@ void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0,
     state->lineTo(x1, y1);
     state->lineTo(x2, y2);
     state->closePath();
-    out->fill(state);
+    if (!contentIsHidden())
+      out->fill(state);
     state->clearPath();
   } else {
     x01 = 0.5 * (x0 + x1);
@@ -2951,7 +2965,8 @@ void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) {
 		   patch->x[1][0], patch->y[1][0],
 		   patch->x[0][0], patch->y[0][0]);
     state->closePath();
-    out->fill(state);
+    if (!contentIsHidden())
+      out->fill(state);
     state->clearPath();
   } else {
     for (i = 0; i < 4; ++i) {
@@ -3411,8 +3426,10 @@ void Gfx::doShowText(GooString *s) {
       originX *= state->getFontSize();
       originY *= state->getFontSize();
       state->textTransformDelta(originX, originY, &tOriginX, &tOriginY);
-      out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
-		    tdx, tdy, tOriginX, tOriginY, code, n, u, uLen);
+      if (!contentIsHidden()) {
+        out->drawChar(state, state->getCurX() + riseX, state->getCurY() + riseY,
+		      tdx, tdy, tOriginX, tOriginY, code, n, u, uLen);
+      }
       state->shift(tdx, tdy);
       p += n;
       len -= n;
@@ -3449,7 +3466,8 @@ void Gfx::doShowText(GooString *s) {
       dy *= state->getFontSize();
     }
     state->textTransformDelta(dx, dy, &tdx, &tdy);
-    out->drawString(state, s);
+    if (!contentIsHidden())
+      out->drawString(state, s);
     state->shift(tdx, tdy);
   }
 
@@ -3643,7 +3661,8 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
     obj1.free();
 
     // draw it
-    out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
+    if (!contentIsHidden())
+      out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
 
   } else {
 
@@ -3833,13 +3852,15 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
 
     // draw it
     if (haveSoftMask) {
-      out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
-			       maskStr, maskWidth, maskHeight, maskColorMap);
+      if (!contentIsHidden()) {
+        out->drawSoftMaskedImage(state, ref, str, width, height, colorMap,
+				 maskStr, maskWidth, maskHeight, maskColorMap);
+      }
       delete maskColorMap;
-    } else if (haveExplicitMask) {
+    } else if (haveExplicitMask && !contentIsHidden ()) {
       out->drawMaskedImage(state, ref, str, width, height, colorMap,
 			   maskStr, maskWidth, maskHeight, maskInvert);
-    } else {
+    } else if (!contentIsHidden()) {
       out->drawImage(state, ref, str, width, height, colorMap,
 		     haveColorKeyMask ? maskColors : (int *)NULL, inlineImg);
     }
@@ -4153,10 +4174,33 @@ void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
 // marked content operators
 //------------------------------------------------------------------------
 
+struct MarkedContentStack {
+  GBool ocSuppressed;       // are we ignoring content based on OptionalContent?
+  MarkedContentStack *next; // next object on stack
+};
+
+void Gfx::popMarkedContent() {
+  MarkedContentStack *mc = mcStack;
+  mcStack = mc->next;
+  delete mc;
+}
+
+void Gfx::pushMarkedContent() {
+  MarkedContentStack *mc = new MarkedContentStack();
+  mc->ocSuppressed = gFalse;
+  mc->next = mcStack;
+  mcStack = mc;
+}
+
+GBool Gfx::contentIsHidden() {
+  return mcStack && mcStack->ocSuppressed;
+}
+
 void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
-  // TODO: we really need to be adding this to the markedContentStack
+  // push a new stack entry
+  pushMarkedContent();
+  
   OCGs *contentConfig = catalog->getOptContentConfig();
-	
   char* name0 = args[0].getName();
   if ( strncmp( name0, "OC", 2) == 0 && contentConfig) {
     if ( numArgs >= 2 ) {
@@ -4168,7 +4212,8 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
       if ( res->lookupMarkedContentNF( name1, &markedContent ) ) {
 	if ( markedContent.isRef() ) {
 	  bool visible = contentConfig->optContentIsVisible( &markedContent );
-	  ocSuppressed = !(visible);
+	  MarkedContentStack *mc = mcStack;
+	  mc->ocSuppressed = !(visible);
        }
       } else {
 	error(getPos(), "DID NOT find %s", name1);
@@ -4178,7 +4223,6 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
     }
   }
 
-
   if (printCommands) {
     printf("  marked content: %s ", args[0].getName());
     if (numArgs == 2)
@@ -4195,8 +4239,9 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
 }
 
 void Gfx::opEndMarkedContent(Object args[], int numArgs) {
-  // TODO: we should turn this off based on the markedContentStack
-  ocSuppressed = false;
+  // pop the stack
+  if (mcStack)
+    popMarkedContent();
   out->endMarkedContent(state);
 }
 
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index 2dc9315..b14c5a2 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -61,6 +61,7 @@ class PDFRectangle;
 class AnnotBorder;
 class AnnotColor;
 class Catalog;
+struct MarkedContentStack;
 
 //------------------------------------------------------------------------
 
@@ -171,7 +172,6 @@ private:
   GBool profileCommands;	// profile the drawing commands (for debugging)
   GfxResources *res;		// resource stack
   int updateLevel;
-  GBool ocSuppressed;		// are we ignoring content based on OptionalContent?
 
   GfxState *state;		// current graphics state
   GBool fontChanged;		// set if font or text matrix has changed
@@ -181,7 +181,7 @@ private:
 				//   page/form/pattern
   int formDepth;
 
-  GooList *markedContentStack;	// current BMC/EMC stack
+  MarkedContentStack *mcStack;	// current BMC/EMC stack
 
   Parser *parser;		// parser for page content stream(s)
 
@@ -329,6 +329,9 @@ private:
   void opBeginMarkedContent(Object args[], int numArgs);
   void opEndMarkedContent(Object args[], int numArgs);
   void opMarkPoint(Object args[], int numArgs);
+  GBool contentIsHidden();
+  void pushMarkedContent();
+  void popMarkedContent();
 
   void pushResources(Dict *resDict);
   void popResources();
commit d1a330ae0a257a39dc0cb55f81cbab288121ef35
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Nov 8 20:20:00 2008 +0100

    Minor code cleanup and consistency issues

diff --git a/poppler/OptionalContent.cc b/poppler/OptionalContent.cc
index ffffd6f..4a3d4a9 100644
--- a/poppler/OptionalContent.cc
+++ b/poppler/OptionalContent.cc
@@ -51,7 +51,7 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
       ocg.free();
       break;
     }
-    OptionalContentGroup *thisOptionalContentGroup = new OptionalContentGroup(ocg.getDict(), xref);
+    OptionalContentGroup *thisOptionalContentGroup = new OptionalContentGroup(ocg.getDict());
     ocg.free();
     ocgList.arrayGetNF(i, &ocg);
     // TODO: we should create a lookup map from Ref to the OptionalContentGroup
@@ -159,7 +159,7 @@ OptionalContentGroup* OCGs::findOcgByRef( const Ref &ref)
   OptionalContentGroup *ocg = NULL;
   for (int i=0; i < optionalContentGroups->getLength(); ++i) {
     ocg = (OptionalContentGroup*)optionalContentGroups->get(i);
-    if ( (ocg->ref().num == ref.num) && (ocg->ref().gen == ref.gen) ) {
+    if ( (ocg->getRef().num == ref.num) && (ocg->getRef().gen == ref.gen) ) {
       return ocg;
     }
   }
@@ -206,7 +206,7 @@ bool OCGs::optContentIsVisible( Object *dictRef )
       }
     } else if (ocg.isRef()) {
       OptionalContentGroup* oc = findOcgByRef( ocg.getRef() );      
-      if ( !oc || oc->state() == OptionalContentGroup::Off ) {
+      if ( !oc || oc->getState() == OptionalContentGroup::Off ) {
 	result = false;
       } else {
 	result = true ;
@@ -216,7 +216,7 @@ bool OCGs::optContentIsVisible( Object *dictRef )
     policy.free();
   } else if ( dictType.isName("OCG") ) {
     OptionalContentGroup* oc = findOcgByRef( dictRef->getRef() );
-    if ( !oc || oc->state() == OptionalContentGroup::Off ) {
+    if ( !oc || oc->getState() == OptionalContentGroup::Off ) {
       result=false;
     }
   }
@@ -233,7 +233,7 @@ bool OCGs::allOn( Array *ocgArray )
     ocgArray->getNF(i, &ocgItem);
     if (ocgItem.isRef()) {
       OptionalContentGroup* oc = findOcgByRef( ocgItem.getRef() );      
-      if ( oc && oc->state() == OptionalContentGroup::Off ) {
+      if ( oc && oc->getState() == OptionalContentGroup::Off ) {
 	return false;
       }
     }
@@ -248,7 +248,7 @@ bool OCGs::allOff( Array *ocgArray )
     ocgArray->getNF(i, &ocgItem);
     if (ocgItem.isRef()) {
       OptionalContentGroup* oc = findOcgByRef( ocgItem.getRef() );      
-      if ( oc && oc->state() == OptionalContentGroup::On ) {
+      if ( oc && oc->getState() == OptionalContentGroup::On ) {
 	return false;
       }
     }
@@ -263,7 +263,7 @@ bool OCGs::anyOn( Array *ocgArray )
     ocgArray->getNF(i, &ocgItem);
     if (ocgItem.isRef()) {
       OptionalContentGroup* oc = findOcgByRef( ocgItem.getRef() );      
-      if ( oc && oc->state() == OptionalContentGroup::On ) {
+      if ( oc && oc->getState() == OptionalContentGroup::On ) {
 	return true;
       }
     }
@@ -278,7 +278,7 @@ bool OCGs::anyOff( Array *ocgArray )
     ocgArray->getNF(i, &ocgItem);
     if (ocgItem.isRef()) {
       OptionalContentGroup* oc = findOcgByRef( ocgItem.getRef() );      
-      if ( oc && oc->state() == OptionalContentGroup::Off ) {
+      if ( oc && oc->getState() == OptionalContentGroup::Off ) {
 	return true;
       }
     }
@@ -288,7 +288,7 @@ bool OCGs::anyOff( Array *ocgArray )
 
 //------------------------------------------------------------------------
 
-OptionalContentGroup::OptionalContentGroup(Dict *ocgDict, XRef *xrefA) : m_name(NULL)
+OptionalContentGroup::OptionalContentGroup(Dict *ocgDict) : m_name(NULL)
 {
   Object ocgName;
   ocgDict->lookup("Name", &ocgName);
@@ -306,7 +306,7 @@ OptionalContentGroup::OptionalContentGroup(GooString *label)
   m_state = On;
 }
 
-GooString* OptionalContentGroup::name() const
+GooString* OptionalContentGroup::getName() const
 {
   return m_name;
 }
@@ -316,7 +316,7 @@ void OptionalContentGroup::setRef(const Ref ref)
   m_ref = ref;
 }
 
-Ref OptionalContentGroup::ref() const
+Ref OptionalContentGroup::getRef() const
 {
   return m_ref;
 }
diff --git a/poppler/OptionalContent.h b/poppler/OptionalContent.h
index 0ffbc44..b6136c3 100644
--- a/poppler/OptionalContent.h
+++ b/poppler/OptionalContent.h
@@ -66,18 +66,18 @@ class OptionalContentGroup {
 public:
   enum State { On, Off };
 
-  OptionalContentGroup(Dict *dict, XRef *xrefA);
+  OptionalContentGroup(Dict *dict);
 
   OptionalContentGroup(GooString *label);
 
   ~OptionalContentGroup();
 
-  GooString* name() const;
+  GooString* getName() const;
 
-  Ref ref() const;
+  Ref getRef() const;
   void setRef(const Ref ref);
 
-  State state() { return m_state; };
+  State getState() { return m_state; };
   void setState(State state) { m_state = state; };
 
 private:
diff --git a/qt4/src/poppler-optcontent.cc b/qt4/src/poppler-optcontent.cc
index af916ab..ecbc23a 100644
--- a/qt4/src/poppler-optcontent.cc
+++ b/qt4/src/poppler-optcontent.cc
@@ -73,8 +73,8 @@ namespace Poppler
   {
     m_group = group;
     m_parent = 0;
-    m_name = UnicodeParsedString( group->name() );
-    if ( group->state() == OptionalContentGroup::On ) {
+    m_name = UnicodeParsedString( group->getName() );
+    if ( group->getState() == OptionalContentGroup::On ) {
       m_state = OptContentItem::On;
     } else {
       m_state = OptContentItem::Off;
@@ -162,7 +162,7 @@ namespace Poppler
     for (int i = 0; i < ocgs->getLength(); ++i) {
       OptionalContentGroup *ocg = static_cast<OptionalContentGroup*>(ocgs->get(i));
       OptContentItem *node = new OptContentItem( ocg );
-      m_optContentItems.insert( QString::number(ocg->ref().num), node);
+      m_optContentItems.insert( QString::number(ocg->getRef().num), node);
     }
 
     if ( optContent->getOrderArray() == 0 ) {
diff --git a/qt4/tests/check_optcontent.cpp b/qt4/tests/check_optcontent.cpp
index 247c67b..ec988b8 100644
--- a/qt4/tests/check_optcontent.cpp
+++ b/qt4/tests/check_optcontent.cpp
@@ -184,8 +184,8 @@ void TestOptionalContent::checkVisibilitySetting()
     OptionalContentGroup *ocgA = ocgs->findOcgByRef( ref21 );
     QVERIFY( ocgA );
 
-    QVERIFY( (ocgA->name()->cmp("A")) == 0 );
-    QCOMPARE( ocgA->state(), OptionalContentGroup::On );
+    QVERIFY( (ocgA->getName()->cmp("A")) == 0 );
+    QCOMPARE( ocgA->getState(), OptionalContentGroup::On );
 
     Object ref28obj;
     ref28obj.initRef( 28, 0 );
@@ -193,8 +193,8 @@ void TestOptionalContent::checkVisibilitySetting()
     OptionalContentGroup *ocgB = ocgs->findOcgByRef( ref28 );
     QVERIFY( ocgB );
 
-    QVERIFY( (ocgB->name()->cmp("B")) == 0 );
-    QCOMPARE( ocgB->state(), OptionalContentGroup::On );
+    QVERIFY( (ocgB->getName()->cmp("B")) == 0 );
+    QCOMPARE( ocgB->getState(), OptionalContentGroup::On );
 
     // turn one Off
     ocgA->setState( OptionalContentGroup::Off );
commit 995e9dc180dc36d0f3d540a0fc073f911021fed9
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Oct 19 12:44:13 2008 +0200

    Delete the optContent object if it's invalid

diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc
index 4d29dc9..025c8a9 100644
--- a/poppler/Catalog.cc
+++ b/poppler/Catalog.cc
@@ -202,6 +202,10 @@ Catalog::Catalog(XRef *xrefA) {
   // get the Optional Content dictionary
   if (catDict.dictLookup("OCProperties", &optContentProps)->isDict()) {
     optContent = new OCGs(&optContentProps, xref);
+    if (!optContent->isOk ()) {
+      delete optContent;
+      optContent = NULL;
+    }
   }
   optContentProps.free();
 
diff --git a/poppler/OptionalContent.cc b/poppler/OptionalContent.cc
index 204872b..ffffd6f 100644
--- a/poppler/OptionalContent.cc
+++ b/poppler/OptionalContent.cc
@@ -31,6 +31,7 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
   m_orderArray(0), m_rBGroupsArray(), m_xref(xref)
 {
   // we need to parse the dictionary here, and build optionalContentGroups
+  ok = gTrue;
   optionalContentGroups = new GooList();
 
   Object ocgList;
@@ -38,6 +39,7 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
   if (!ocgList.isArray()) {
     error(-1, "Expected the optional content group list, but wasn't able to find it, or it isn't an Array");
     ocgList.free();
+    ok = gFalse;
     return;
   }
 
@@ -66,6 +68,7 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
     error(-1, "Expected the default config, but wasn't able to find it, or it isn't a Dictionary");
     defaultOcgConfig.free();
     ocgList.free();
+    ok = gFalse;
     return;
   }
 #if 0
diff --git a/poppler/OptionalContent.h b/poppler/OptionalContent.h
index 6afa023..0ffbc44 100644
--- a/poppler/OptionalContent.h
+++ b/poppler/OptionalContent.h
@@ -32,6 +32,9 @@ public:
   OCGs(Object *ocgObject, XRef *xref);
   ~OCGs();
 
+  // Is OCGS valid?
+  GBool isOk() { return ok; }
+  
   bool hasOCGs();
   GooList *getOCGs() const { return optionalContentGroups; }
 
@@ -43,6 +46,8 @@ public:
   bool optContentIsVisible( Object *dictRef );
 
 private:
+  GBool ok;
+  
   bool allOn( Array *ocgArray );
   bool allOff( Array *ocgArray );
   bool anyOn( Array *ocgArray );


More information about the poppler mailing list