[poppler] 5 commits - poppler/Annot.cc poppler/Annot.h poppler/Link.cc poppler/Movie.cc poppler/Movie.h qt4/src

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Mon Mar 8 05:39:11 PST 2010


 poppler/Annot.cc         |  317 +++++++++++++----------------------------------
 poppler/Annot.h          |   77 -----------
 poppler/Link.cc          |    4 
 poppler/Movie.cc         |  269 ++++++++++++++++++++++++++++++++-------
 poppler/Movie.h          |   35 ++++-
 qt4/src/poppler-movie.cc |   11 +
 6 files changed, 351 insertions(+), 362 deletions(-)

New commits:
commit a00532f509c19c5455e0db5068db95dd4583e8dd
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Mon Mar 8 14:22:53 2010 +0100

    Check for Null instead of None to know whether a dict entry is present
    
    Dict::lookup returns obj->initNull() when the key is not found.

diff --git a/poppler/Movie.cc b/poppler/Movie.cc
index 709ccfb..e51f6b6 100644
--- a/poppler/Movie.cc
+++ b/poppler/Movie.cc
@@ -159,7 +159,7 @@ void MovieParameters::parseMovieActivation(Object* aDict,
 					   int rotationAngleA) {
   Object obj1;
 
-  if (!aDict->dictLookup("Start", &obj1)->isNone()) {
+  if (!aDict->dictLookup("Start", &obj1)->isNull()) {
     if (obj1.isInt()) {
       // If it is representable as an integer (subject to the implementation limit for
       // integers, as described in Appendix C), it should be specified as such.
@@ -196,7 +196,7 @@ void MovieParameters::parseMovieActivation(Object* aDict,
   }
   obj1.free();
 
-  if (!aDict->dictLookup("Duration", &obj1)->isNone()) {
+  if (!aDict->dictLookup("Duration", &obj1)->isNull()) {
     if (obj1.isInt()) {
       duration.units = obj1.getInt();
     }
@@ -483,7 +483,7 @@ Movie::Movie(Object *movieDict, Object *aDict) {
   //
   // movie poster
   //
-  if (!movieDict->dictLookupNF("Poster", &poster)->isNone()) {
+  if (!movieDict->dictLookupNF("Poster", &poster)->isNull()) {
     if (poster.isRef() || poster.isStream()) {
       showPoster = gTrue;
     } else if (poster.isBool()) {
commit b51e66c9a7e2f7f39ae1edf8bda02a7bc1ad4ebd
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Mon Mar 8 14:15:22 2010 +0100

    [annots] Create appearance stream for Movie Annotations when not defined
    
    See bug #23108

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 411723e..5ee31ac 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -16,7 +16,7 @@
 // Copyright (C) 2006 Scott Turner <scotty1024 at mac.com>
 // Copyright (C) 2007, 2008 Julien Rebetez <julienr at svn.gnome.org>
 // Copyright (C) 2007-2009 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2007-2009 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2007-2010 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2007, 2008 Iñigo Martínez <inigomartinez at gmail.com>
 // Copyright (C) 2007 Jeff Muizelaar <jeff at infidigm.net>
 // Copyright (C) 2008 Pino Toscano <pino at kde.org>
@@ -4080,6 +4080,107 @@ void AnnotMovie::initialize(XRef *xrefA, Catalog *catalog, Dict* dict) {
   movieDict.free();
 }
 
+void AnnotMovie::draw(Gfx *gfx, GBool printing) {
+  Object obj;
+
+  if (!isVisible (printing))
+    return;
+
+  if (appearance.isNull() && movie->getShowPoster()) {
+    int width, height;
+    Object poster;
+    movie->getPoster(&poster);
+    movie->getAspect(&width, &height);
+
+    if (width != -1 && height != -1 && !poster.isNone()) {
+      MemStream *mStream;
+
+      appearBuf = new GooString ();
+      appearBuf->append ("q\n");
+      appearBuf->appendf ("{0:d} 0 0 {1:d} 0 0 cm\n", width, height);
+      appearBuf->append ("/MImg Do\n");
+      appearBuf->append ("Q\n");
+
+      Object imgDict;
+      imgDict.initDict(xref);
+      imgDict.dictSet ("MImg", &poster);
+
+      Object resDict;
+      resDict.initDict(xref);
+      resDict.dictSet ("XObject", &imgDict);
+
+      Object formDict, obj1, obj2;
+      formDict.initDict(xref);
+      formDict.dictSet("Length", obj1.initInt(appearBuf->getLength()));
+      formDict.dictSet("Subtype", obj1.initName("Form"));
+      formDict.dictSet("Name", obj1.initName("FRM"));
+      obj1.initArray(xref);
+      obj1.arrayAdd(obj2.initInt(0));
+      obj1.arrayAdd(obj2.initInt(0));
+      obj1.arrayAdd(obj2.initInt(width));
+      obj1.arrayAdd(obj2.initInt(height));
+      formDict.dictSet("BBox", &obj1);
+      obj1.initArray(xref);
+      obj1.arrayAdd(obj2.initInt(1));
+      obj1.arrayAdd(obj2.initInt(0));
+      obj1.arrayAdd(obj2.initInt(0));
+      obj1.arrayAdd(obj2.initInt(1));
+      obj1.arrayAdd(obj2.initInt(-width / 2));
+      obj1.arrayAdd(obj2.initInt(-height / 2));
+      formDict.dictSet("Matrix", &obj1);
+      formDict.dictSet("Resources", &resDict);
+
+      Object aStream;
+      mStream = new MemStream(copyString(appearBuf->getCString()), 0,
+			      appearBuf->getLength(), &formDict);
+      mStream->setNeedFree(gTrue);
+      aStream.initStream(mStream);
+      delete appearBuf;
+
+      Object objDict;
+      objDict.initDict(xref);
+      objDict.dictSet ("FRM", &aStream);
+
+      resDict.initDict(xref);
+      resDict.dictSet ("XObject", &objDict);
+
+      appearBuf = new GooString ();
+      appearBuf->append ("q\n");
+      appearBuf->appendf ("0 0 {0:d} {1:d} re W n\n", width, height);
+      appearBuf->append ("q\n");
+      appearBuf->appendf ("0 0 {0:d} {1:d} re W n\n", width, height);
+      appearBuf->appendf ("1 0 0 1 {0:d} {1:d} cm\n", width / 2, height / 2);
+      appearBuf->append ("/FRM Do\n");
+      appearBuf->append ("Q\n");
+      appearBuf->append ("Q\n");
+
+      Object appearDict;
+      appearDict.initDict(xref);
+      appearDict.dictSet("Length", obj1.initInt(appearBuf->getLength()));
+      appearDict.dictSet("Subtype", obj1.initName("Form"));
+      appearDict.dictSet("Resources", &resDict);
+      obj1.initArray(xref);
+      obj1.arrayAdd(obj2.initInt(0));
+      obj1.arrayAdd(obj2.initInt(0));
+      obj1.arrayAdd(obj2.initInt(width));
+      obj1.arrayAdd(obj2.initInt(height));
+      appearDict.dictSet("BBox", &obj1);
+
+      MemStream *appearStream = new MemStream(copyString(appearBuf->getCString()), 0,
+					      appearBuf->getLength(), &appearDict);
+      appearStream->setNeedFree(gTrue);
+      appearance.initStream(appearStream);
+      delete appearBuf;
+    }
+    poster.free();
+  }
+
+  // draw the appearance stream
+  appearance.fetch(xref, &obj);
+  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color, 1,
+		 rect->x1, rect->y1, rect->x2, rect->y2);
+  obj.free();
+}
 
 //------------------------------------------------------------------------
 // AnnotScreen
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 14cafd0..d4de6f6 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2006 Scott Turner <scotty1024 at mac.com>
 // Copyright (C) 2007, 2008 Julien Rebetez <julienr at svn.gnome.org>
-// Copyright (C) 2007-2009 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2007-2010 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2007, 2008 Iñigo Martínez <inigomartinez at gmail.com>
 // Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
 // Copyright (C) 2008 Hugo Mercier <hmercier31 at gmail.com>
@@ -703,6 +703,8 @@ class AnnotMovie: public Annot {
   AnnotMovie(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
   ~AnnotMovie();
 
+  virtual void draw(Gfx *gfx, GBool printing);
+
   GooString* getTitle() { return title; }
   Movie* getMovie() { return movie; }
 
commit fae59411852e5c2c45825c5ea963318f1ed5dc6a
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Mon Mar 8 14:07:09 2010 +0100

    Fix handling of poster in Movie
    
    Poster is not always a stream, it can be a boolean too. Also, get the
    reference when available instead of fetching the stream.

diff --git a/poppler/Movie.cc b/poppler/Movie.cc
index fab467d..709ccfb 100644
--- a/poppler/Movie.cc
+++ b/poppler/Movie.cc
@@ -432,7 +432,7 @@ void Movie::initialize() {
   embeddedStream = NULL;
   width = -1;
   height = -1;
-  posterStream = NULL;
+  showPoster = gFalse;
 }
 
 Movie::~Movie() {
@@ -444,9 +444,7 @@ Movie::~Movie() {
   if (embeddedStream && (!embeddedStream->decRef())) {
     delete embeddedStream;
   }
-  if (posterStream && (!posterStream->decRef())) {
-    delete posterStream;
-  }
+  poster.free();
 }
 
 Movie::Movie(Object *movieDict, Object *aDict) {
@@ -485,13 +483,15 @@ Movie::Movie(Object *movieDict, Object *aDict) {
   //
   // movie poster
   //
-  if (!movieDict->dictLookup("Poster", &obj1)->isNone()) {
-    if (obj1.isStream()) {
-      // "copy" stream
-      posterStream = obj1.getStream();
-      posterStream->incRef();
+  if (!movieDict->dictLookupNF("Poster", &poster)->isNone()) {
+    if (poster.isRef() || poster.isStream()) {
+      showPoster = gTrue;
+    } else if (poster.isBool()) {
+      showPoster = obj1.getBool();
+      poster.free();
+    } else {
+      poster.free();
     }
-    obj1.free();
   }
 
   if (aDict->isDict()) {
@@ -621,9 +621,8 @@ Movie* Movie::copy() {
 
   if (new_movie->embeddedStream)
     new_movie->embeddedStream->incRef();
-  
-  if (new_movie->posterStream)
-    new_movie->posterStream->incRef();
+
+  poster.copy(&new_movie->poster);
 
   return new_movie;
 }
diff --git a/poppler/Movie.h b/poppler/Movie.h
index c49b12c..f601cf1 100644
--- a/poppler/Movie.h
+++ b/poppler/Movie.h
@@ -160,7 +160,8 @@ class Movie {
   void outputToFile(FILE*);
 
   void getAspect (int *widthA, int *heightA) { *widthA = width; *heightA = height; }
-  Stream* getPosterStream() { return posterStream; }
+  Object *getPoster (Object *obj) { return poster.copy(obj); }
+  GBool getShowPoster () { return showPoster; }
 
   Movie* copy();
 
@@ -177,7 +178,8 @@ class Movie {
   int width;                               // Aspect
   int height;                              // Aspect
 
-  Stream* posterStream;
+  Object poster;
+  GBool showPoster;
 
   GBool isEmbedded;
 
commit a451f83d101bf265a1e7e2a17c0b320895e70f4e
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 7 12:22:57 2010 +0100

    Save width, height (aspect) in Movie object and provide getAspect() method

diff --git a/poppler/Movie.cc b/poppler/Movie.cc
index 0b4d838..fab467d 100644
--- a/poppler/Movie.cc
+++ b/poppler/Movie.cc
@@ -430,6 +430,8 @@ void Movie::initialize() {
   contentType = NULL;
   isEmbedded = gFalse;
   embeddedStream = NULL;
+  width = -1;
+  height = -1;
   posterStream = NULL;
 }
 
@@ -457,7 +459,6 @@ Movie::Movie(Object *movieDict, Object *aDict) {
   }
   obj1.free();
 
-  int width = 0, height = 0;
   if (movieDict->dictLookup("Aspect", &obj1)->isArray()) {
     Array* aspect = obj1.getArray();
     if (aspect->getLength() >= 2) {
diff --git a/poppler/Movie.h b/poppler/Movie.h
index 7de3518..c49b12c 100644
--- a/poppler/Movie.h
+++ b/poppler/Movie.h
@@ -159,6 +159,7 @@ class Movie {
   // write embedded stream to file
   void outputToFile(FILE*);
 
+  void getAspect (int *widthA, int *heightA) { *widthA = width; *heightA = height; }
   Stream* getPosterStream() { return posterStream; }
 
   Movie* copy();
@@ -173,6 +174,9 @@ class Movie {
   // "Best Effort" parameters
   MovieParameters BE;
 
+  int width;                               // Aspect
+  int height;                              // Aspect
+
   Stream* posterStream;
 
   GBool isEmbedded;
commit f88d469f860da17055fc4b98b64aef241fcf0185
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Mar 6 12:33:40 2010 +0100

    Move Movie objects parsing code from Annot to Movie

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 16eea0d..411723e 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -4049,21 +4049,12 @@ AnnotMovie::AnnotMovie(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
   Annot(xrefA, dict, catalog, obj) {
   type = typeMovie;
   initialize(xrefA, catalog, dict);
-
-  movie = new Movie();
-  movie->parseAnnotMovie(this);
 }
 
 AnnotMovie::~AnnotMovie() {
   if (title)
     delete title;
-  if (fileName)
-    delete fileName;
   delete movie;
-
-  if (posterStream && (!posterStream->decRef())) {
-    delete posterStream;
-  }
 }
 
 void AnnotMovie::initialize(XRef *xrefA, Catalog *catalog, Dict* dict) {
@@ -4077,237 +4068,16 @@ void AnnotMovie::initialize(XRef *xrefA, Catalog *catalog, Dict* dict) {
   obj1.free();
 
   Object movieDict;
-  Object aDict;
-
-  // default values
-  fileName = NULL;
-  width = 0;
-  height = 0;
-  rotationAngle = 0;
-  rate = 1.0;
-  volume = 1.0;
-  showControls = false;
-  repeatMode = repeatModeOnce;
-  synchronousPlay = false;
-  
-  hasFloatingWindow = false;
-  isFullscreen = false;
-  FWScaleNum = 1;
-  FWScaleDenum = 1;
-  FWPosX = 0.5;
-  FWPosY = 0.5;
-
   if (dict->lookup("Movie", &movieDict)->isDict()) {
-    Object obj2;
-    if (getFileSpecNameForPlatform(movieDict.dictLookup("F", &obj1), &obj2)) {
-      fileName = obj2.getString()->copy();
-      obj2.free();
-    }
-    obj1.free();
-
-    if (movieDict.dictLookup("Aspect", &obj1)->isArray()) {
-      Array* aspect = obj1.getArray();
-      if (aspect->getLength() >= 2) {
-	Object tmp;
-	if( aspect->get(0, &tmp)->isNum() ) {
-	  width = (int)floor( aspect->get(0, &tmp)->getNum() + 0.5 );
-	}
-	tmp.free();
-	if( aspect->get(1, &tmp)->isNum() ) {
-	  height = (int)floor( aspect->get(1, &tmp)->getNum() + 0.5 );
-	}
-	tmp.free();
-      }
-    }
-    obj1.free();
-
-    if (movieDict.dictLookup("Rotate", &obj1)->isInt()) {
-      // round up to 90°
-      rotationAngle = (((obj1.getInt() + 360) % 360) % 90) * 90;
-    }
-    obj1.free();
-
-    //
-    // movie poster
-    //
-    posterType = posterTypeNone;
-    posterStream = NULL;
-    if (!movieDict.dictLookup("Poster", &obj1)->isNone()) {
-      if (obj1.isBool()) {
-	GBool v = obj1.getBool();
-	if (v)
-	  posterType = posterTypeFromMovie;
-      }
-      
-      if (obj1.isStream()) {
-	posterType = posterTypeStream;
-	
-	// "copy" stream
-	posterStream = obj1.getStream();
-	posterStream->incRef();
-      }
-
-      obj1.free();
-    }
-
+    Object aDict;
+    dict->lookup("A", &aDict);
+    movie = Movie::fromMovie (&movieDict, &aDict);
+    aDict.free();
+  } else {
+    error(-1, "Bad Annot Movie");
+    ok = gFalse;
   }
   movieDict.free();
-
-
-  // activation dictionary parsing ...
-
-  if (dict->lookup("A", &aDict)->isDict()) {
-    if (!aDict.dictLookup("Start", &obj1)->isNone()) {
-      if (obj1.isInt()) {
-	// If it is representable as an integer (subject to the implementation limit for
-	// integers, as described in Appendix C), it should be specified as such.
-
-	start.units = obj1.getInt();
-      }
-      if (obj1.isString()) {
-	// If it is not representable as an integer, it should be specified as an 8-byte
-	// string representing a 64-bit twos-complement integer, most significant
-	// byte first.
-
-	// UNSUPPORTED
-      }
-
-      if (obj1.isArray()) {
-	Array* a = obj1.getArray();
-
-	Object tmp;
-	a->get(0, &tmp);
-	if (tmp.isInt()) {
-	  start.units = tmp.getInt();
-	}
-	if (tmp.isString()) {
-	  // UNSUPPORTED
-	}
-	tmp.free();
-
-	a->get(1, &tmp);
-	if (tmp.isInt()) {
-	  start.units_per_second = tmp.getInt();
-	}
-	tmp.free();
-      }
-    }
-    obj1.free();
-
-    if (!aDict.dictLookup("Duration", &obj1)->isNone()) {
-      if (obj1.isInt()) {
-	duration.units = obj1.getInt();
-      }
-      if (obj1.isString()) {
-	// UNSUPPORTED
-      }
-
-      if (obj1.isArray()) {
-	Array* a = obj1.getArray();
-
-	Object tmp;
-	a->get(0, &tmp);
-	if (tmp.isInt()) {
-	  duration.units = tmp.getInt();
-	}
-	if (tmp.isString()) {
-	  // UNSUPPORTED
-	}
-	tmp.free();
-
-	a->get(1, &tmp);
-	if (tmp.isInt()) {
-	  duration.units_per_second = tmp.getInt();
-	}
-	tmp.free();
-      }
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("Rate", &obj1)->isNum()) {
-      rate = obj1.getNum();
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("Volume", &obj1)->isNum()) {
-      volume = obj1.getNum();
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("ShowControls", &obj1)->isBool()) {
-      showControls = obj1.getBool();
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("Synchronous", &obj1)->isBool()) {
-      synchronousPlay = obj1.getBool();
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("Mode", &obj1)->isName()) {
-      char* name = obj1.getName();
-      if (!strcmp(name, "Once"))
-	repeatMode = repeatModeOnce;
-      if (!strcmp(name, "Open"))
-	repeatMode = repeatModeOpen;
-      if (!strcmp(name, "Repeat"))
-	repeatMode = repeatModeRepeat;
-      if (!strcmp(name,"Palindrome"))
-	repeatMode = repeatModePalindrome;
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("FWScale", &obj1)->isArray()) {
-      // the presence of that entry implies that the movie is to be played
-      // in a floating window
-      hasFloatingWindow = true;
-
-      Array* scale = obj1.getArray();
-      if (scale->getLength() >= 2) {
-	Object tmp;
-	if (scale->get(0, &tmp)->isInt()) {
-	  FWScaleNum = tmp.getInt();
-	}
-	tmp.free();
-	if (scale->get(1, &tmp)->isInt()) {
-	  FWScaleDenum = tmp.getInt();
-	}
-	tmp.free();
-      }
-
-      // detect fullscreen mode
-      if ((FWScaleNum == 999) && (FWScaleDenum == 1)) {
-	isFullscreen = true;
-      }
-    }
-    obj1.free();
-
-    if (aDict.dictLookup("FWPosition", &obj1)->isArray()) {
-      Array* pos = obj1.getArray();
-      if (pos->getLength() >= 2) {
-	Object tmp;
-	if (pos->get(0, &tmp)->isNum()) {
-	  FWPosX = tmp.getNum();
-	}
-	tmp.free();
-	if (pos->get(1, &tmp)->isNum()) {
-	  FWPosY = tmp.getNum();
-	}
-	tmp.free();
-      }
-    }
-  }
-  aDict.free();
-}
-
-void AnnotMovie::getMovieSize(int& width, int& height) {
-  width = this->width;
-  height = this->height;
-}
-
-void AnnotMovie::getZoomFactor(int& num, int& denum) {
-  num = FWScaleNum;
-  denum = FWScaleDenum;
 }
 
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 0059845..14cafd0 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -699,89 +699,18 @@ private:
 
 class AnnotMovie: public Annot {
  public:
-  enum PosterType {
-    posterTypeNone,
-    posterTypeStream,
-    posterTypeFromMovie
-  };
-
-  enum RepeatMode {
-    repeatModeOnce,
-    repeatModeOpen,
-    repeatModeRepeat,
-    repeatModePalindrome
-  };
-
-  struct Time {
-    Time() { units_per_second = 0; }
-    Gulong units;
-    int units_per_second; // 0 : defined by movie
-  };
-
   AnnotMovie(XRef *xrefA, PDFRectangle *rect, Movie *movieA, Catalog *catalog);
   AnnotMovie(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
   ~AnnotMovie();
 
   GooString* getTitle() { return title; }
-  GooString* getFileName() { return fileName; }
-  int getRotationAngle() { return rotationAngle; }
-
-  PosterType getPosterType() { return posterType; }
-  Stream* getPosterStream() { return posterStream; }
-
-  Time getStart() { return start; }
-  Time getDuration() { return duration; }
-  double getRate() { return rate; }
-  double getVolume() { return volume; }
-
-  GBool getShowControls() { return showControls; }
-  RepeatMode getRepeatMode() { return repeatMode; }
-  GBool getSynchronousPlay() { return synchronousPlay; }
-
-  GBool needFloatingWindow() { return hasFloatingWindow; }
-  GBool needFullscreen() { return isFullscreen; }
-  
-  
-  void getMovieSize(int& width, int& height);
-  void getZoomFactor(int& num, int& denum);
-  void getWindowPosition(double& x, double& y) { x = FWPosX; y = FWPosY; }
-
   Movie* getMovie() { return movie; }
 
  private:
   void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
 
   GooString* title;      // T
-  GooString* fileName;   // Movie/F
-
-  int width;             // Movie/Aspect
-  int height;            // Movie/Aspect
-  int rotationAngle;     // Movie/Rotate
-
-  PosterType posterType; // Movie/Poster
-  Stream* posterStream;
-
-  Time start;            // A/Start
-  Time duration;         // A/Duration
-  double rate;           // A/Rate
-  double volume;         // A/Volume
-  
-  GBool showControls;    // A/ShowControls
-  
-  RepeatMode repeatMode; // A/Mode
-  
-  GBool synchronousPlay; // A/Synchronous
-
-  // floating window
-  GBool hasFloatingWindow; 
-  unsigned short FWScaleNum; // A/FWScale
-  unsigned short FWScaleDenum;
-  GBool isFullscreen;
-
-  double FWPosX;         // A/FWPosition
-  double FWPosY; 
-
-  Movie* movie;
+  Movie* movie;          // Movie + A
 };
 
 
diff --git a/poppler/Link.cc b/poppler/Link.cc
index 5f3b8bd..3649d25 100644
--- a/poppler/Link.cc
+++ b/poppler/Link.cc
@@ -712,10 +712,8 @@ LinkRendition::LinkRendition(Object *Obj) {
       // retrieve rendition object
       Obj->dictLookup("R", &renditionObj);
       if (renditionObj.isDict()) {
+	movie = Movie::fromMediaRendition(&renditionObj);
 
-	movie = new Movie();
-	movie->parseMediaRendition(&renditionObj);
-	
 	if (screenRef.num == -1) {
 	  error(-1, "Action Rendition : Rendition without Screen Annotation !");
 	}
diff --git a/poppler/Movie.cc b/poppler/Movie.cc
index e29c64e..0b4d838 100644
--- a/poppler/Movie.cc
+++ b/poppler/Movie.cc
@@ -5,6 +5,7 @@
 //---------------------------------------------------------------------------------
 // Hugo Mercier <hmercier31[at]gmail.com> (c) 2008
 // Pino Toscano <pino at kde.org> (c) 2008
+// Carlos Garcia Campos <carlosgc at gnome.org> (c) 2010
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -21,7 +22,9 @@
 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 //*********************************************************************************
 
+#include <math.h>
 #include "Movie.h"
+#include "FileSpec.h"
 
 #include <GooList.h>
 
@@ -141,7 +144,8 @@ MovieParameters::MovieParameters() {
   repeatCount = 1.0;
   opacity = 1.0;
   showControls = gFalse;
-
+  synchronousPlay = gFalse;
+  repeatMode = repeatModeOnce;
   
   start.units = 0;
   duration.units = 0;  
@@ -150,46 +154,162 @@ MovieParameters::MovieParameters() {
 MovieParameters::~MovieParameters() {
 }
 
-void MovieParameters::parseAnnotMovie(AnnotMovie* annot) {
-  windowParams.relativeTo = MovieWindowParameters::windowRelativeToDesktop;
+void MovieParameters::parseMovieActivation(Object* aDict,
+					   int width, int height,
+					   int rotationAngleA) {
+  Object obj1;
 
-  if (annot->needFloatingWindow()) {
-    windowParams.type = MovieWindowParameters::movieWindowFloating;
+  if (!aDict->dictLookup("Start", &obj1)->isNone()) {
+    if (obj1.isInt()) {
+      // If it is representable as an integer (subject to the implementation limit for
+      // integers, as described in Appendix C), it should be specified as such.
+
+      start.units = obj1.getInt();
+    }
+    if (obj1.isString()) {
+      // If it is not representable as an integer, it should be specified as an 8-byte
+      // string representing a 64-bit twos-complement integer, most significant
+      // byte first.
+
+      // UNSUPPORTED
+    }
+
+    if (obj1.isArray()) {
+      Array* a = obj1.getArray();
+
+      Object tmp;
+      a->get(0, &tmp);
+      if (tmp.isInt()) {
+        start.units = tmp.getInt();
+      }
+      if (tmp.isString()) {
+        // UNSUPPORTED
+      }
+      tmp.free();
+
+      a->get(1, &tmp);
+      if (tmp.isInt()) {
+        start.units_per_second = tmp.getInt();
+      }
+      tmp.free();
+    }
   }
-  if (annot->needFullscreen()) {
-    windowParams.type = MovieWindowParameters::movieWindowFullscreen;
+  obj1.free();
+
+  if (!aDict->dictLookup("Duration", &obj1)->isNone()) {
+    if (obj1.isInt()) {
+      duration.units = obj1.getInt();
+    }
+    if (obj1.isString()) {
+      // UNSUPPORTED
+    }
+
+    if (obj1.isArray()) {
+      Array* a = obj1.getArray();
+
+      Object tmp;
+      a->get(0, &tmp);
+      if (tmp.isInt()) {
+        duration.units = tmp.getInt();
+      }
+      if (tmp.isString()) {
+        // UNSUPPORTED
+      }
+      tmp.free();
+
+      a->get(1, &tmp);
+      if (tmp.isInt()) {
+        duration.units_per_second = tmp.getInt();
+      }
+      tmp.free();
+    }
+  }
+  obj1.free();
+
+  if (aDict->dictLookup("Rate", &obj1)->isNum()) {
+    rate = obj1.getNum();
+  }
+  obj1.free();
+
+  rotationAngle = rotationAngleA;
+
+  if (aDict->dictLookup("Volume", &obj1)->isNum()) {
+    // convert volume to [0 100]
+    volume = int((obj1.getNum() + 1.0) * 50);
   }
+  obj1.free();
 
-  int w, h;
-  int znum, zdenum;
-  annot->getMovieSize(w, h);
-  annot->getZoomFactor(znum, zdenum);
-  windowParams.width = int(w * double(znum) / zdenum);
-  windowParams.height = int(h * double(znum) / zdenum);
+  if (aDict->dictLookup("ShowControls", &obj1)->isBool()) {
+    showControls = obj1.getBool();
+  }
+  obj1.free();
 
-  double x,y;
-  annot->getWindowPosition(x,y);
-  windowParams.XPosition = x;
-  windowParams.YPosition = y;
+  if (aDict->dictLookup("Synchronous", &obj1)->isBool()) {
+    synchronousPlay = obj1.getBool();
+  }
+  obj1.free();
+
+  if (aDict->dictLookup("Mode", &obj1)->isName()) {
+    char* name = obj1.getName();
+    if (!strcmp(name, "Once")) {
+      repeatMode = repeatModeOnce;
+    } else if (!strcmp(name, "Open")) {
+      repeatMode = repeatModeOpen;
+    } else if (!strcmp(name, "Repeat")) {
+      repeatMode = repeatModeRepeat;
+      repeatCount = 0.0;
+    } else if (!strcmp(name,"Palindrome")) {
+      repeatMode = repeatModePalindrome;
+    }
+  }
+  obj1.free();
 
-  rate = annot->getRate();
-  // convert volume to [0 100]
-  volume = int((annot->getVolume() + 1.0) * 50);
+  windowParams.relativeTo = MovieWindowParameters::windowRelativeToDesktop;
 
-  AnnotMovie::RepeatMode mode = annot->getRepeatMode();
-  if (mode == AnnotMovie::repeatModeRepeat)
-    repeatCount = 0.0;
+  int znum = 1, zdenum = 1;
+  if (aDict->dictLookup("FWScale", &obj1)->isArray()) {
+    // the presence of that entry implies that the movie is to be played
+    // in a floating window
+    windowParams.type = MovieWindowParameters::movieWindowFloating;
 
-  showControls = annot->getShowControls();
+    Array* scale = obj1.getArray();
+    if (scale->getLength() >= 2) {
+      Object tmp;
+      if (scale->get(0, &tmp)->isInt()) {
+        znum = tmp.getInt();
+      }
+      tmp.free();
+      if (scale->get(1, &tmp)->isInt()) {
+        zdenum = tmp.getInt();
+      }
+      tmp.free();
+    }
 
-  AnnotMovie::Time tStart = annot->getStart();
-  AnnotMovie::Time tDuration = annot->getDuration();
+    // detect fullscreen mode
+    if (znum == 999 && zdenum == 1) {
+      windowParams.type = MovieWindowParameters::movieWindowFullscreen;
+    }
+  }
+  obj1.free();
 
-  start.units = tStart.units;
-  start.units_per_second = tStart.units_per_second;
+  windowParams.width = int(width * double(znum) / zdenum);
+  windowParams.height = int(height * double(znum) / zdenum);
 
-  duration.units = tDuration.units;
-  duration.units_per_second = tDuration.units_per_second;
+  if (aDict->dictLookup("FWPosition", &obj1)->isArray()) {
+    Array* pos = obj1.getArray();
+    if (pos->getLength() >= 2) {
+      Object tmp;
+      if (pos->get(0, &tmp)->isNum()) {
+        windowParams.XPosition = tmp.getNum();
+      }
+      tmp.free();
+      if (pos->get(1, &tmp)->isNum()) {
+        windowParams.YPosition = tmp.getNum();
+      }
+      tmp.free();
+    }
+  }
+  obj1.free();
 }
 
 void MovieParameters::parseMediaPlayParameters(Object* obj) {
@@ -305,7 +425,7 @@ void MovieParameters::parseMediaScreenParameters(Object* obj) {
   }
 }
 
-Movie::Movie() {
+void Movie::initialize() {
   fileName = NULL;
   contentType = NULL;
   isEmbedded = gFalse;
@@ -327,26 +447,64 @@ Movie::~Movie() {
   }
 }
 
-void Movie::parseAnnotMovie(AnnotMovie* annot) {
-  // AnnotMovie is not embedded
-  isEmbedded = gFalse;
+Movie::Movie(Object *movieDict, Object *aDict) {
+  initialize();
 
-  fileName = annot->getFileName()->copy();
+  Object obj1, obj2;
+  if (getFileSpecNameForPlatform(movieDict->dictLookup("F", &obj1), &obj2)) {
+    fileName = obj2.getString()->copy();
+    obj2.free();
+  }
+  obj1.free();
+
+  int width = 0, height = 0;
+  if (movieDict->dictLookup("Aspect", &obj1)->isArray()) {
+    Array* aspect = obj1.getArray();
+    if (aspect->getLength() >= 2) {
+      Object tmp;
+      if( aspect->get(0, &tmp)->isNum() ) {
+        width = (int)floor( aspect->get(0, &tmp)->getNum() + 0.5 );
+      }
+      tmp.free();
+      if( aspect->get(1, &tmp)->isNum() ) {
+        height = (int)floor( aspect->get(1, &tmp)->getNum() + 0.5 );
+      }
+      tmp.free();
+    }
+  }
+  obj1.free();
 
-  if (annot->getPosterStream()) {
-    posterStream = annot->getPosterStream();
-    posterStream->incRef();
+  int rotationAngle = 0;
+  if (movieDict->dictLookup("Rotate", &obj1)->isInt()) {
+    // round up to 90°
+    rotationAngle = (((obj1.getInt() + 360) % 360) % 90) * 90;
+  }
+  obj1.free();
+
+  //
+  // movie poster
+  //
+  if (!movieDict->dictLookup("Poster", &obj1)->isNone()) {
+    if (obj1.isStream()) {
+      // "copy" stream
+      posterStream = obj1.getStream();
+      posterStream->incRef();
+    }
+    obj1.free();
   }
 
-  MH.parseAnnotMovie(annot);
-  // deep copy of MH to BE
-  // (no distinction is made with AnnotMovie)
-  memcpy(&BE, &MH, sizeof(MH));
+  if (aDict->isDict()) {
+    MH.parseMovieActivation(aDict, width, height, rotationAngle);
+    // deep copy of MH to BE
+    // (no distinction is made with AnnotMovie)
+    memcpy(&BE, &MH, sizeof(MH));
+  }
 }
 
-void Movie::parseMediaRendition(Object* obj) {
-
+Movie::Movie(Object* obj) {
   Object tmp, tmp2;
+
+  initialize();
   if (obj->dictLookup("S", &tmp)->isName()) {
     if (!strcmp(tmp.getName(), "MR")) { // it's a media rendition
 
@@ -427,6 +585,15 @@ void Movie::parseMediaRendition(Object* obj) {
   }
 }
 
+Movie *Movie::fromMovie(Object *objMovie, Object *objAct)
+{
+  return new Movie (objMovie, objAct);
+}
+
+Movie *Movie::fromMediaRendition(Object *objRend)
+{
+  return new Movie (objRend);
+}
 
 void Movie::outputToFile(FILE* fp) {
   embeddedStream->reset();
diff --git a/poppler/Movie.h b/poppler/Movie.h
index 16584ad..7de3518 100644
--- a/poppler/Movie.h
+++ b/poppler/Movie.h
@@ -4,6 +4,7 @@
 // 
 //---------------------------------------------------------------------------------
 // Hugo Mercier <hmercier31[at]gmail.com> (c) 2008
+// Carlos Garcia Campos <carlosgc at gnome.org> (c) 2010
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -24,7 +25,6 @@
 #define _MOVIE_H_
 
 #include "Object.h"
-#include "Annot.h"
 
 class GooList;
 
@@ -79,8 +79,8 @@ struct MovieParameters {
   void parseMediaPlayParameters(Object* playObj);
   // parse from a "Media Screen Parameters" dictionary
   void parseMediaScreenParameters(Object* screenObj);
-  // parse from a AnnotMovie object
-  void parseAnnotMovie(AnnotMovie* annot);
+  // parse from a "Movie Activation" dictionary
+  void parseMovieActivation(Object* actObj, int width, int height, int rotationAngle);
 
   enum MovieFittingPolicy {
     fittingMeet = 0,
@@ -91,6 +91,13 @@ struct MovieParameters {
     fittingUndefined
   };
 
+  enum MovieRepeatMode {
+    repeatModeOnce,
+    repeatModeOpen,
+    repeatModeRepeat,
+    repeatModePalindrome
+  };
+
   struct MovieTime {
     MovieTime() { units_per_second = 0; }
     Gulong units;
@@ -128,16 +135,18 @@ struct MovieParameters {
 
   GBool showControls;                      // false
 
+  GBool synchronousPlay;                   // false
+  MovieRepeatMode repeatMode;              // repeatModeOnce
+
   MovieWindowParameters windowParams;
 };
 
 class Movie {
  public:
-  Movie();
   ~Movie();
 
-  void parseAnnotMovie(AnnotMovie* annot);
-  void parseMediaRendition(Object* obj);
+  static Movie *fromMovie(Object *objMovie, Object *objAct);
+  static Movie *fromMediaRendition(Object *objRend);
 
   MovieParameters* getMHParameters() { return &MH; }
   MovieParameters* getBEParameters() { return &BE; }
@@ -155,6 +164,10 @@ class Movie {
   Movie* copy();
 
  private:
+  Movie(Object *objMovie, Object *objAct);
+  Movie(Object *objRend);
+  void initialize();
+
   // "Must Honor" parameters
   MovieParameters MH;
   // "Best Effort" parameters
diff --git a/qt4/src/poppler-movie.cc b/qt4/src/poppler-movie.cc
index 50e60f9..7941be1 100644
--- a/qt4/src/poppler-movie.cc
+++ b/qt4/src/poppler-movie.cc
@@ -48,10 +48,13 @@ MovieObject::MovieObject( AnnotMovie *ann )
 {
 	m_movieData = new MovieData();
 	m_movieData->m_movieObj = ann->getMovie()->copy();
-	ann->getMovieSize( m_movieData->m_size.rwidth(), m_movieData->m_size.rheight() );
-	m_movieData->m_rotation = ann->getRotationAngle();
-	m_movieData->m_showControls = ann->getShowControls();
-	m_movieData->m_playMode = (MovieObject::PlayMode)ann->getRepeatMode();
+
+	MovieParameters *mp = m_movieData->m_movieObj->getMHParameters();
+	m_movieData->m_size.setWidth(mp->windowParams.width);
+	m_movieData->m_size.setHeight(mp->windowParams.height);
+	m_movieData->m_rotation = mp->rotationAngle;
+	m_movieData->m_showControls = mp->showControls;
+	m_movieData->m_playMode = (MovieObject::PlayMode)mp->repeatMode;
 }
 
 MovieObject::~MovieObject()


More information about the poppler mailing list