[poppler] poppler Digest, Vol 73, Issue 27
Carlos Garcia Campos
carlosgc at gnome.org
Wed Mar 23 07:18:41 PDT 2011
Excerpts from srinivas adicherla's message of mié mar 23 08:30:32 +0100 2011:
> Hi Carlos,
Hi,
> Thank you for your valuable suggestions. I made the changes
> according to that. I attached a new patch with this.
Thanks!
> - I have some doubt when setting a 'Rendition' action, we have two options
> one is to set 'OP' other one is 'JS'. I am asking the user to pass the
> Javascript and set it as a stream here.
Since both options are required when the other one is not present, I
would add two constructors, one for OP, and another one for JS.
LinkRendition::LinkRendition(XRef *xrefA, MediaRendition *rendition, int operation, Annot *annot);
LinkRendition::LinkRendition(XRef *xrefA, Object *js);
> - One more is i wrote a new function 'get_file_name_from_path' is it fine?
> what is the good place to add this function.
yes, just rename it to follow poppler coding style to something like:
getFileNameFromPath();
> Please give suggestions again.
See comments below
> Thanks
Index: poppler-0.16.2/poppler/Link.cc
===================================================================
--- poppler-0.16.2/poppler/Link.cc (revision 12)
+++ poppler-0.16.2/poppler/Link.cc (working copy)
@@ -44,6 +44,7 @@
#include "Sound.h"
#include "FileSpec.h"
#include "Rendition.h"
+#include "XRef.h"
//------------------------------------------------------------------------
// LinkAction
@@ -738,6 +739,32 @@
}
}
+LinkRendition::LinkRendition(Annot *annot, const char *video_file,Object *obj) {
This method should receive the XRef, and the MediaRendition object
already created. See the contructors I suggested above.
+ Object obj1;
+ XRef *xref = annot->getXRef();
+ renditionObj.initDict(xref);
+ Ref annotref = annot->getRef();
+ renditionObj.dictSet("Type", obj1.initName("Action"));
+ renditionObj.dictSet("S", obj1.initName("Rendition"));
+ if (obj->isInt()) {
+ renditionObj.dictSet("OP", obj);
+ renditionObj.dictSet("AN", obj1.initRef(annotref.num, annotref.gen));
+ }
+ else {
+ renditionObj.dictSet("JS", obj);
+ }
+
+ // Media Rendition
+ Object MRendition;
+ MediaRendition *MR = new MediaRendition(annot, video_file);
+ MRendition = MR->getMediaRendition();
+
+ Ref newRef;
+ newRef = xref->addIndirectObject(&MRendition);
+ obj->initRef(newRef.num, newRef.gen);
+ renditionObj.dictSet("R", &obj1);
+}
+
LinkRendition::~LinkRendition() {
renditionObj.free();
screenRef.free();
Index: poppler-0.16.2/poppler/Rendition.cc
===================================================================
--- poppler-0.16.2/poppler/Rendition.cc (revision 12)
+++ poppler-0.16.2/poppler/Rendition.cc (working copy)
@@ -24,6 +24,7 @@
#include <math.h>
#include "Rendition.h"
+#include "XRef.h"
#include "FileSpec.h"
MediaWindowParameters::MediaWindowParameters() {
@@ -366,6 +367,40 @@
tmp2.free();
}
+MediaRendition::MediaRendition(Annot *annot, const char *mediafile) {
Pass the XRef directly instead of passing the annot object just to get
the XRef
+ Object obj1, obj2;
+
+ XRef *xref = annot->getXRef();
+ mediaRendition.initDict(xref);
+ mediaRendition.dictSet("S", obj1.initName("MR"));
+
+ // Media Clip Dictionary
+ Object MClipDict;
+ MClipDict.initDict(xref);
+ MClipDict.dictSet("S", obj1.initName("MCD"));
+
+ //if (mimetype)
+ //MClipDict.dictSet("CT", obj3.initString(new GooString(mimetype)));
There's a contentType variable for this, so make sure it's updated so
that MediaRendition::getContentType() will work. Why is this commented?
+ obj1.initString(new GooString("TEMPACCESS"));
+ obj2.initDict(xref);
+ obj2.dictSet("TF", &obj1);
+ MClipDict.dictSet("P", &obj2);
The Permissions dictionary is optional, why are you hardcoding
TEMPACCESS here? We are not even parsing TF when creating a
MediaRendition from an existing dictionary.
+ // File Specification Dictionary
+ Object *fsDict;
+ fsDict = annot->createFilespec(mediafile);
As Pino suggested this should probably be moved to FileSpec.cc since
it's not specific to annotations.
+
+ Ref newRef;
+ newRef = xref->addIndirectObject(fsDict);
+ obj2.initRef(newRef.num, newRef.gen);
+ MClipDict.dictSet("D", &obj2);
You should initialize the fileName, isEmbedded and embeddedStream variables,
maybe it's the time to add a FileSpec class so that this methos just
receives a FileSpec object instead of a filename.
+ newRef = xref->addIndirectObject(&MClipDict);
+ obj2.initRef(newRef.num, newRef.gen);
+ mediaRendition.dictSet("C", &obj2);
ok variable should be initialized to gTrue.
+}
+
void MediaRendition::outputToFile(FILE* fp) {
if (!isEmbedded)
return;
Index: poppler-0.16.2/poppler/Rendition.h
===================================================================
--- poppler-0.16.2/poppler/Rendition.h (revision 12)
+++ poppler-0.16.2/poppler/Rendition.h (working copy)
@@ -25,6 +25,7 @@
#define _RENDITION_H_
#include "Object.h"
+#include "Annot.h"
struct MediaWindowParameters {
@@ -118,6 +119,7 @@
class MediaRendition {
public:
MediaRendition(Object *obj);
+ MediaRendition(Annot *annot, const char *mediafile);
~MediaRendition();
GBool isOk () { return ok; }
@@ -128,6 +130,7 @@
GooString* getContentType() { return contentType; }
GooString* getFileName() { return fileName; }
+ Object getMediaRendition() {return mediaRendition;}
GBool getIsEmbedded() { return isEmbedded; }
Stream* getEmbbededStream() { return embeddedStream; }
// write embedded stream to file
@@ -145,6 +148,7 @@
GBool isEmbedded;
+ Object mediaRendition;
mediaRendition should be initilized in the other constructor too,
simply copy the given object:
obj->copy(&mediaRendition);
GooString* contentType;
// if it's embedded
Index: poppler-0.16.2/poppler/Annot.cc
===================================================================
--- poppler-0.16.2/poppler/Annot.cc (revision 12)
+++ poppler-0.16.2/poppler/Annot.cc (working copy)
+void AnnotScreen::setTitle(GooString *title) {
+ if (title)
+ title = new GooString(title);
+ else
+ title = new GooString();
save the title as a class attr, and add getTitle() method. Make sure
the string is correctly encoded, see Annot::setContents() for example.
+ Object obj1;
+ obj1.initString(title->copy());
+ update ("T", &obj1);
+ delete(title);
+}
+GBool AnnotScreen::setAction(const char* video_file, const char* mimetype, const char* img_file, const char* js) {
A screen annot can be used to trigger any action type, not only
rendition actions, so this should be something like:
GBool AnnotScreen::setAction(LinkAction *actionA);
+ if (!video_file) {
+ error(-1, "Need to pass the video file");
+ return gFalse;
+ }
+
+ // Extract the video name from the file uri
+ const char *video_name = get_file_name_from_path (video_file);
+
+ Object obj1, obj2, obj3, obj4;
+
+ GooString *title = new GooString(video_name);
+ setTitle(title);
+ setContents(title);
+ delete(title);
title and contents should be set by the caller, the frontends in this
case.
+ Ref imgRef;
+ Object imgXObj;
+ imgXObj.initDict(xref);
+ imgXObj.dictSet("Type", obj1.initName("XObject"));
+ imgXObj.dictSet("Subtype", obj2.initName("Image"));
+
+ if (img_file) {
+ FILE *imgfp;
+ if (!(imgfp = fopen(img_file, "rb"))) {
+ error(-1, "Couldn't open file: %s",img_file);
+ return gFalse;
+ }
+ unsigned char h[10];
+ fread(h, 1, 10, imgfp);
+ fseek(imgfp, 0, SEEK_SET);
+
+ MemStream *imgStream = NULL;
+ // Load the stream from the png file
+ if (h[0] == 0x89 && h[1] == 0x50 && h[2] == 0x4E && h[3] == 0x47)
+ imgStream = load_from_png (imgfp, &imgXObj);
+ // Load the stream from the jpeg file
+ else if(h[0] == 0xFF && h[1] == 0xD8 && h[6] == 0x4A && h[7] == 0x46 && h[8] == 0x49 && h[9] == 0x46)
+ imgStream = load_from_jpeg (imgfp, &imgXObj);
+ else {
+ error(-1, "Image format cannot be supported, only png/jpeg\n");
+ return gFalse;
+ }
+
+ if (imgStream) {
+ obj2.initStream(imgStream);
+ appearBuf = new GooString("/Im1 Do");
+ double bbox[4];
+ bbox[0] = bbox[1] = 0;
+ bbox[2] = bbox[3] = 1;
+ createResourcesDict("Im1", &obj2, "GS0", 1.0, NULL, &obj4);
+ createForm(bbox, gFalse, &obj4, &obj1);
+
+ Ref appRef = xref->addIndirectObject(&obj1);
+ obj2.initDict(xref);
+ obj2.dictSet("N", obj3.initRef(appRef.num, appRef.gen));
+ annotObj.dictSet("AP", &obj2);
+
+ obj2.initStream(imgStream);
+ createResourcesDict("Im1", &obj2, "GS0", 1.0, NULL, &obj1);
+ createForm(bbox, gFalse, &obj1, &obj4);
+ appRef = xref->addIndirectObject(&obj4);
+
+ obj2.initDict(xref); // MK dictionary
+ obj2.dictSet("I", obj3.initRef(appRef.num, appRef.gen));
+ annotObj.dictSet("MK", &obj2);
+ }
+ }
I think it would be better to add a generic mehtod to set the annot
appearance stream from an image, something like
Annot::setAppearanceFromFile() and call it from the frontends instead
of doing it here.
+ if (js == NULL)
+ obj1.initInt(0);
+ else {
+ obj2.initDict(xref);
+ obj2.dictSet("Length", obj3.initInt(strlen(js)));
+ MemStream *jsstream = new MemStream(copyString((char*)js), 0, strlen(js), &obj2);
+ obj1.initStream(jsstream);
+ }
+
+ LinkRendition *rendition = new LinkRendition(this, video_file, &obj1);
You should update the action variable instead.
+ Object *renditionObj = rendition->getRenditionObject();
+ Ref newRef = xref->addIndirectObject(renditionObj);
+ obj1.initRef(newRef.num, newRef.gen);
rendition object should be added by the MediaRendition constructor
like we currently does for annotations, and here you only need to get
the Ref.
+ annotObj.dictSet("A", &obj1);
+
+ return gTrue;
+}
+
//------------------------------------------------------------------------
// AnnotStamp
//------------------------------------------------------------------------
Index: poppler-0.16.2/glib/poppler-annot.cc
===================================================================
--- poppler-0.16.2/glib/poppler-annot.cc (revision 12)
+++ poppler-0.16.2/glib/poppler-annot.cc (working copy)
@@ -332,7 +332,52 @@
return poppler_annot;
}
+/**
+ * poppler_annot_screen_new:
+ * @doc: a #PopplerDocument
+ * @rect: a #PopplerRectangle
+ *
+ * Creates a new Screen annotation that will be
+ * located on @rect when added to a page. See
+ * poppler_page_add_annot()
+ *
+ * Return value: A newly created #PopplerAnnotScreen annotation
+ *
+ */
+PopplerAnnot *
+poppler_annot_screen_new (PopplerDocument *doc,
+ PopplerRectangle *rect)
+{
+ Annot *annot;
+ PDFRectangle pdf_rect(rect->x1, rect->y1,
+ rect->x2, rect->y2);
+ annot = new AnnotScreen (doc->doc->getXRef(), &pdf_rect, doc->doc->getCatalog());
+ return _poppler_annot_screen_new (annot);
+}
+
+/**
+ * poppler_annot_screen_set_action:
+ * @poppler_annot: a #PopplerAnnot
+ * @video_file: pass the path of the video to be embed
+ * @mimetype: pass the mimetype of the video to put in the Media Clip Dictionary
+ * @img_file: pass png/jpeg image file for poster
+ * @js: set the JS as this javascript stream in rendition action else if it is null set OP
+
+ * Set the action for the screen annotation specified @poppler_annot
+ *
+ */
+void
+poppler_annot_screen_set_action (PopplerAnnot *poppler_annot,
+ const char* video_file,
+ const char* mimetype,
+ const char* img_file,
+ const char* js)
This is still wrong, you should be able to set any action type to a
screen annotation.
--
Carlos Garcia Campos
PGP key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x523E6462
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/poppler/attachments/20110323/094c9927/attachment.pgp>
More information about the poppler
mailing list