Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-3893

QPrintEngine PDF basic outlining Table of contents + Patch

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Unresolved
    • P3: Somewhat important
    • None
    • 4.5.0
    • GUI: Printing
    • None

    Description

      Adds basic outlining(TOC), to the printer class and implements it for the PDF printer. This will enable, the on-the-side bookmarks/toc/outline that one often finds in pdf readers. Two functions are added to the print engine api, one for starting an outline section, as arguments it takes the name of the section, the page where it starts, and the location on the page, (0.0,0.0) being top left and (1.0, 1.0) being bottom right. And a second call that ends a section. This way sections are handled in a stack like fashion.

      Patch:

      diff -ur qt-x11-opensource-src-4.5.0-old/src/gui/painting/qprintengine.h qt-x11-opensource-src-4.5.0/src/gui/painting/qprintengine.h
      — qt-x11-opensource-src-4.5.0-old/src/gui/painting/qprintengine.h 2009-02-25 22:09:23.000000000 +0100
      +++ qt-x11-opensource-src-4.5.0/src/gui/painting/qprintengine.h 2009-03-10 20:31:32.000000000 +0100
      @@ -95,6 +95,8 @@
      virtual QVariant property(PrintEnginePropertyKey key) const = 0;

      virtual bool newPage() = 0;
      + virtual void beginSectionOutline(const QString & text, uint page, const QPointF & location)

      {Q_UNUSED(text); Q_UNUSED(page); Q_UNUSED(location);}

      + virtual void endSectionOutline() {}
      virtual bool abort() = 0;

      virtual int metric(QPaintDevice::PaintDeviceMetric) const = 0;
      diff -ur qt-x11-opensource-src-4.5.0-old/src/gui/painting/qprintengine_pdf.cpp qt-x11-opensource-src-4.5.0/src/gui/painting/qprintengine_pdf.cpp
      — qt-x11-opensource-src-4.5.0-old/src/gui/painting/qprintengine_pdf.cpp 2009-02-25 22:09:23.000000000 +0100
      +++ qt-x11-opensource-src-4.5.0/src/gui/painting/qprintengine_pdf.cpp 2009-03-10 20:31:32.000000000 +0100
      @@ -115,6 +115,28 @@
      state = QPrinter::Idle;
      }

      +void QPdfEngine::beginSectionOutline(const QString & text, uint p, const QPointF & location) {
      + Q_D(QPdfEngine);
      + if(d->outlineCurrent == NULL)

      { + if(d->outlineRoot) delete d->outlineRoot; + d->outlineCurrent = d->outlineRoot = new QPdfEnginePrivate::OutlineItem(QString(), 0, QPointF() ); + }

      + QPdfEnginePrivate::OutlineItem * i = new QPdfEnginePrivate::OutlineItem(text, p, location);
      + i->parent = d->outlineCurrent;
      + i->prev = d->outlineCurrent->lastChild;
      + if(d->outlineCurrent->firstChild)
      + d->outlineCurrent->lastChild->next = i;
      + else
      + d->outlineCurrent->firstChild = i;
      + d->outlineCurrent->lastChild = i;
      + d->outlineCurrent = i;
      +}
      +
      +void QPdfEngine::endSectionOutline()

      { + Q_D(QPdfEngine); + if(d->outlineCurrent) d->outlineCurrent = d->outlineCurrent->parent; +}

      +
      QPdfEngine::~QPdfEngine()
      {
      }
      @@ -156,6 +178,24 @@
      bool QPdfEngine::end()
      {
      Q_D(QPdfEngine);
      +
      + if(d->outlineRoot)

      { + d->outlineRoot->obj = d->requestObject(); + d->writeOutlineChildren(d->outlineRoot); + d->addXrefEntry(d->outlineRoot->obj); + d->xprintf("<</Type /Outlines /First %d 0 R\n/Last %d 0 R>>\nendobj\n", + d->outlineRoot->firstChild->obj,d->outlineRoot->lastChild->obj); + }

      +
      + d->catalog = d->addXrefEntry(-1);
      + d->xprintf("<<\n"
      + "/Type /Catalog\n"
      + "/Pages %d 0 R\n", d->pageRoot);
      + if(d->outlineRoot)
      + d->xprintf("/Outlines %d 0 R\n"
      + "/PageMode /UseOutlines", d->outlineRoot->obj);
      + d->xprintf(">>\n"
      + "endobj\n");
      d->writeTail();

      d->stream->unsetDevice();
      @@ -305,14 +345,59 @@
      stream = new QDataStream;
      pageOrder = QPrinter::FirstPageFirst;
      orientation = QPrinter::Portrait;
      + outlineRoot = NULL;
      + outlineCurrent = NULL;
      fullPage = false;
      }

      QPdfEnginePrivate::~QPdfEnginePrivate()

      { + if(outlineRoot) delete outlineRoot; delete stream; }

      +void QPdfEnginePrivate::writeOutlineChildren(OutlineItem * node) {
      + for(OutlineItem * i = node->firstChild; i != NULL; i = i->next)
      + i->obj = requestObject();
      + for(OutlineItem * i = node->firstChild; i != NULL; i = i->next) {
      + QPdfEnginePrivate::writeOutlineChildren;
      + addXrefEntry(i->obj);
      + xprintf("<</Title (",254,255);
      + const ushort * tit = i->text.utf16();
      + int l=0;
      + for(;tit[l]; ++l);
      + ushort * buff = new ushort[l*2+2];
      + buff[0] = 0xFEFF;
      + char * buff_;
      + for(int j=0; j<l;++j) buff[j+1] = tit[j];
      + ++l;
      + buff_ = (char*)buff;
      + if((unsigned char)buff_[0] == 0xFF)
      + for(int j=0; j < l;++j)

      { + char t=buff_[j*2]; + buff_[j*2]=buff_[j*2+1]; + buff_[j*2+1]=t; + }

      +
      + stream->writeRawData(buff_, l*2);
      + streampos += l*2;
      + delete[] buff;
      + double x = width() * qMax(0.0,qMin(1.0,i->location.x()));
      + double y = height() * qMax(0.0,qMin(1.0,(1.0 - i->location.y())));
      + xprintf(")\n"
      + " /Parent %d 0 R\n"
      + " /Dest [%d 0 R /XYZ %lf %lf null]\n"
      + " /Count 0\n",
      + i->parent->obj,
      + pages[i->page<pages.size()?i->page:pages.size()-1],x,y);
      + if(i->next) xprintf(" /Next %d 0 R\n", i->next->obj);
      + if(i->prev) xprintf(" /Prev %d 0 R\n", i->prev->obj);
      + if(i->firstChild) xprintf(" /First %d 0 R\n", i->firstChild->obj);
      + if(i->lastChild) xprintf(" /Last %d 0 R\n", i->lastChild->obj);
      + xprintf(">>\n"
      + "endobj\n");
      + }
      +}

      #ifdef USE_NATIVE_GRADIENTS
      int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject)
      @@ -901,13 +985,7 @@

      writeInfo();

      • catalog = addXrefEntry(-1);
        pageRoot = requestObject();
      • xprintf("<<\n"
      • "/Type /Catalog\n"
      • "/Pages %d 0 R\n"
      • ">>\n"
      • "endobj\n", pageRoot);

      // graphics state
      graphicsState = addXrefEntry(-1);
      diff -ur qt-x11-opensource-src-4.5.0-old/src/gui/painting/qprintengine_pdf_p.h qt-x11-opensource-src-4.5.0/src/gui/painting/qprintengine_pdf_p.h
      — qt-x11-opensource-src-4.5.0-old/src/gui/painting/qprintengine_pdf_p.h 2009-02-25 22:09:23.000000000 +0100
      +++ qt-x11-opensource-src-4.5.0/src/gui/painting/qprintengine_pdf_p.h 2009-03-10 20:31:32.000000000 +0100
      @@ -113,6 +113,8 @@
      QString author() const;

      void setDevice(QIODevice* dev);
      + void beginSectionOutline(const QString & text, uint page, const QPointF & location);
      + void endSectionOutline();

      private:
      Q_DISABLE_COPY(QPdfEngine)
      @@ -124,5 +126,34 @@
      {
      Q_DECLARE_PUBLIC(QPdfEngine)
      public:
      + class OutlineItem {
      + public:
      + OutlineItem * parent;
      + OutlineItem * next;
      + OutlineItem * prev;
      + OutlineItem * firstChild;
      + OutlineItem * lastChild;
      + uint obj;
      + QString text;
      + uint page;
      + QPointF location;
      +
      + OutlineItem(const QString & t, uint p, const QPointF & l):
      + parent(NULL), next(NULL), prev(NULL), firstChild(NULL), lastChild(NULL),
      + obj(0), text(t), page(p), location(l) {}
      + ~OutlineItem() {
      + OutlineItem * i = firstChild;
      + while(i != NULL)

      { + OutlineItem * n = i->next; + delete i; + i=n; + }

      + }
      + };
      +
      + OutlineItem * outlineRoot;
      + OutlineItem * outlineCurrent;
      + void writeOutlineChildren(OutlineItem * node);
      +
      QPdfEnginePrivate(QPrinter::PrinterMode m);
      ~QPdfEnginePrivate();

      Attachments

        Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

          Activity

            People

              Unassigned Unassigned
              janichol Andy Nichols
              Votes:
              8 Vote for this issue
              Watchers:
              10 Start watching this issue

              Dates

                Created:
                Updated:

                Gerrit Reviews

                  There are no open Gerrit changes