[Poppler-bugs] [Bug 71213] Add new PDFWriter class for writing PDF with printing options

bugzilla-daemon at freedesktop.org bugzilla-daemon at freedesktop.org
Sun Nov 10 06:47:33 PST 2013


https://bugs.freedesktop.org/show_bug.cgi?id=71213

--- Comment #10 from Carlos Garcia Campos <carlosgc at gnome.org> ---
Comment on attachment 88957
  --> https://bugs.freedesktop.org/attachment.cgi?id=88957
Add PDFWriter

Review of attachment 88957:
-----------------------------------------------------------------

This looks great to me. There are several memory leaks and some other things
that could be improved a bit.

::: poppler/PDFWriter.cc
@@ +62,5 @@
> +  pages.push_back(page);
> +}
> +
> +struct PageScale {
> +  int paper;

This can be unsigned

@@ +104,5 @@
> +    std::swap(width, height);
> +
> +  // find smallest paper size that will fit this page
> +  std::priority_queue<PageScale> queue;
> +  for (int i = 0; i < (int)paperSizes.size(); i++) {

Why not using unsigned for i instead of casting?

@@ +186,5 @@
> +      mediaSize->y2 = paperSizes[0].width;
> +      margins->x1 = paperSizes[0].bottom;
> +      margins->x2 = mediaSize->y2 - paperSizes[0].top;
> +      margins->y1 = paperSizes[0].left;
> +      margins->y2 = mediaSize->x2 - paperSizes[0].right;

This block is repeated a lot, I wonder if we could add a helper function,
something like setSizeAndMargins(PDFRectangle *mediaSize, PDFRectangle
*margins, double with, double height, double top, double bottom, double left,
double right); I could be static inline

@@ +376,5 @@
> +void PDFWriter::writePageObject(int pageNum, int copy, PDFRectangle *mediaSize)
> +{
> +  PDFRectangle margins;
> +  Matrix ctm;
> +  Object ctmObj;

This looks unused.

@@ +432,5 @@
> +      obj2.free();
> +    }
> +  } else {
> +    writeObject(&contentsObj);
> +  }

contentsObj.free();

@@ +445,5 @@
> +	outputKey = gFalse;
> +	break;
> +      }
> +      excludeKey++;
> +    }

I think this could be easier to read if you use a helper function to check
whether the entry should be excluded:

if (excludePageEntry(keyName))
  continue;

@@ +453,5 @@
> +      writeObject(pageDict->getValNF(i, &obj1));
> +      outputStr->printf("\n");
> +      obj1.free();
> +    }
> +  }

pageObj.free();

@@ +490,5 @@
> +  outputStr->printf("/Subtype /Form\n");
> +
> +  pageDict->lookup("MediaBox", &obj);
> +  outputStr->printf("/BBox ");
> +  writeObject(&obj);

obj.free();

@@ +494,5 @@
> +  writeObject(&obj);
> +  outputStr->printf("\n");
> +
> +  pageDict->lookup("Resources", &obj);
> +  if (!obj.isNull()) {

This could be a single line:

if (!pageDict->lookup("Resources", &obj)->isNull())
...

@@ +498,5 @@
> +  if (!obj.isNull()) {
> +    outputStr->printf("/Resources ");
> +    writeObject(&obj);
> +    outputStr->printf("\n");
> +  }

obj.free();

@@ +501,5 @@
> +    outputStr->printf("\n");
> +  }
> +
> +  pageDict->lookup("Group", &obj);
> +  if (!obj.isNull()) {

This could be a single line too.

@@ +505,5 @@
> +  if (!obj.isNull()) {
> +    outputStr->printf("/Group ");
> +    writeObject(&obj);
> +    outputStr->printf("\n");
> +  }

obj.free();

@@ +552,5 @@
> +    Stream *str = obj.getStream();
> +    writeStream(str);
> +  } else {
> +    error(errSyntaxError, -1, "Weird page contents");
> +  }

obj.free();

@@ +586,5 @@
> +  outputStr->printf("endobj\n");
> +
> +  beginIndirectObject(&resourcesRef);
> +  outputStr->printf("<< /XObject <<\n");
> +  for (int i = 0; i < (int)xobjectRefs.size(); i++)

You could use unsigned for i here too.

@@ +592,5 @@
> +  outputStr->printf(">> >>\n");
> +  outputStr->printf("endobj\n");
> +
> +  GooString content;
> +  for (int i = 0; i < (int)xobjectRefs.size(); i++) {

Ditto.

@@ +632,5 @@
> +  outputStr->printf("/Kids [");
> +  if (collate) {
> +    for (int cp = 0; cp < copies; cp++) {
> +      if (reverse) {
> +        for (int pg = (int)pageRefs[0].size() - 1; pg >= 0; pg--)

Ditto.

@@ +635,5 @@
> +      if (reverse) {
> +        for (int pg = (int)pageRefs[0].size() - 1; pg >= 0; pg--)
> +          outputStr->printf(" %d %d R", pageRefs[cp][pg].num, pageRefs[cp][pg].gen);
> +      } else {
> +        for (int pg = 0; pg < (int)pageRefs[0].size(); pg++)

Ditto.

@@ +641,5 @@
> +      }
> +    }
> +  } else {
> +    if (reverse) {
> +      for (int pg = (int)pageRefs[0].size() - 1; pg >= 0; pg--) {

Ditto.

@@ +646,5 @@
> +        for (int cp = 0; cp < copies; cp++)
> +          outputStr->printf(" %d %d R", pageRefs[cp][pg].num, pageRefs[cp][pg].gen);
> +      }
> +    } else {
> +      for (int pg = 0; pg < (int)pageRefs[0].size(); pg++)

Ditto.

@@ +662,5 @@
> +  PDFRectangle mediaSize;
> +  int outputPageNum;
> +  int nupPageNum; // 0..numberUp-1
> +  int pageNum;
> +  Object pageObj;

This is unused.

@@ +677,5 @@
> +  // are not marked as they will be included in the XObjects created for
> +  // each page.
> +  outputPageNum = 1;
> +  nupPageNum = 0;
> +  for (int i = 0; i < (int)pages.size(); i++) {

Ditto.

@@ +686,5 @@
> +      Object pageObj;
> +      Ref *refPage = doc->getCatalog()->getPageRef(pageNum);
> +      doc->getXRef()->fetch(refPage->num, refPage->gen, &pageObj);
> +      Dict *pageDict = pageObj.getDict();
> +      doc->markPageObjects(pageDict, yRef, countRef, 0, numberUp > 1 ? gFalse : gTrue);

You don't need a variable for this, you can just pass the dict to the function:

doc->markPageObjects(pageObj.getDict(), ....);

and then

pageObj.free();

@@ +711,5 @@
> +    pageRefs.push_back(refs);
> +  }
> +  outputPageNum = 1;
> +  nupPageNum = 0;
> +  for (int i = 0; i < (int)pages.size(); i++) {

unsigned

@@ +756,5 @@
> +  delete trailerDict;
> +  delete yRef;
> +  delete countRef;
> +
> +  outputStr->close();

delete outputStr;

@@ +757,5 @@
> +  delete yRef;
> +  delete countRef;
> +
> +  outputStr->close();
> +}

I think we could make this function more generic by writing a stream, and then
add writeFile, that creates a FileOutpoutStream and calls the generic one
passing the stream. That way frontends can add a method to write to a stream
instead of creating a file in disk.

::: poppler/PDFWriter.h
@@ +27,5 @@
> +
> +  // order to layout multiple pages on a sheet.
> +  // LR_TB = Left to Right then Top to Bottom
> +  // LR_BT = Left to Right then Bottom to Top etc
> +  enum NumberUpOrder { LR_TB, LR_BT, RL_TB, RL_BT, TB_LR, TB_RL, BT_LR, BT_RL };

Even if it's a bit longer I think it's easier to read if you use full words
instead of abbreviations, and you don't need the comment explaining what the
abbreviations stand for.

::: poppler/Stream.cc
@@ +371,5 @@
> +void OutStream::format(const char *format, ...)
> +{
> +  va_list argptr;
> +  va_start (argptr, format);
> +  GooString *s = GooString::formatv(format, argptr);

Can we do something like this?

GooString s;
s.appendfv(format, argptr);

This way we avoid the alloc/dealloc of the GooString.

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/poppler-bugs/attachments/20131110/4aa2e133/attachment.html>


More information about the Poppler-bugs mailing list