Queries regarding terminologies used in Okular PDF annotation rendering

Tobias Deiminger haxtibal at posteo.de
Mon May 7 19:25:05 UTC 2018


Hi Dileep,

Am 07.05.2018 13:30 schrieb Dileep Sankhla:
> Hi there,
> 
> Please try to answer my following queries:
> 
> 1. What is "viewport"?

the viewport is a child widget of the PageView widget and contains the 
visible part of the content area. Look at okular_ui_areas.png [0] which 
should make it all clear. PageView inherits from QAbstractScrollArea, so 
find viewport documented in Qt docs [1].

> 2. What is "pageview"?

It's the heart of the desktop document UI (btw, there's also an 
unrelated mobile UI in mobile/*). class PageView is defined in 
ui/pageview.{h,cc}. It's a custom QWidget that makes data and logic from 
the core model (core/*) visible und usable. PageView receives most user 
input events (mouse click, key stroke, ...) and handles how pages are 
drawn, scrolled and scaled. It handles also a lot of additional features 
like tooltips and selections. Some functions are delegated to aggregated 
objects like PageViewItem (one per page) or child widgets. But most of 
the UI stuff is directly handled and painted by PageView.

> 3. How does PDF save an annotation in the document?

The question is quite broad and unspecific, can you please rework it?

We both already did an example program that composed a PDF and you 
analysed the decompressed PDF at low level and saw the annotation 
dictionaries. You also have the PDF standard and Leonards book [2] at 
hand. I bet you could mostly answer your own question ;-) You have to 
understand some basic PDF constructs like direct and indirect objects, 
the types (dictionaries, arrays, ...), content streams, resource 
dictionaries and what the cross reference table is. Then the 
decompressed output becomes meaningful in your mind.

> 4. What is "generator" and how does generator render the annotation in

See [3]. class Generator is a (almost pure virtual) Okular interface 
that abstracts the various file formats (pdf, djvu, epub, dvi, txt, 
...). The various concrete generators are implemented in 
generators/<fileformat>/*. Each is compiled into a separate shared 
object that can be loaded as QT plugin at runtime. Often generators just 
forward calls to external libraries like poppler and DjVuLibre where the 
heavy lifting is done. The Generator interface is used by class 
Document. E.g. class Document calls Generator::loadDocument and 
Generator::generatePixmap. So Document doesn't need to know about the 
file format, but only about the Generator interface.

> PDF page? What is the meaning of "rendering" here?

A PDF file contains various kinds of drawing instructions and objects of 
well defined types. You could say PDF is something like a programming 
language. Rendering here means interpreting this "PDF program" (poppler 
has actually Lexer.cc and Parser.cc) and perform all calculations, so 
that finally a bitmap gets constructed, pixel by pixel.

Use gdb to break into Poppler::renderToImage and watch what's going on. 
Within, you should sometime reach Annot::draw which is about rendering 
one Annotation.

> 5. Now how does poppler render the annotation on the PDF page? Is it
> same as the working of the Okular generator?

I'm not sure if I understand the question. Document::requestPixmaps 
requests a pixmap from the Generator. It sets up a PixmapRequest and 
calls Generator::generatePixmap therefore. In the case of PDF Generator, 
the generator then calls Poppler::rednerPageToImage which returns a 
QImage that shows one page. The generator turns this QImage into a 
QPixmap and then signals to Document that generation has been finished 
by means of calling Document::requestDone(). There QPixmap is extracted 
from the PixmapRequest and stored in Document::m_allocatedPixmaps. With 
the next PageView::paintEvent the new Document pixmaps are painted. This 
was a really simplified description. Requests can be asynchronous, and 
instead of rendering the whole page a page can be rendered as several 
smaller images by means of a TilesManager.

> 6. What does "painting" actually mean? And so what does
> "PageView::paintevent" do?

Painting here means to call methods on a QPainter, like 
QPainter::drawPath or QPainter::drawPixmap. It results in graphics on 
the screen, or in a buffer, or somewhere else.

PageView inherits from QWidget. One of the most popular methods of each 
QWidget is QWidget::paintEvent, see Qt docs [4]. This method is called 
by Qt (or your own code), every time a repaint is required. Qt's off the 
shelf widgets have this method readily implemented. But PageView paints 
highly customized and so PageView overrides QWidget::paintEvent to 
provide its own implementation. In the longish path through 
PageView::paintEvent, PageView::drawDocumentOnPainter and 
PagePainter::paintCroppedPageOnPainter we paint the page tiles received 
from generator. We also mix in other graphical items that are not 
delivered by generators (tooltip, move/selection rectangle, ...). If you 
stumble upon "double buffered" or "backbuffering", this just means that 
Okular draws a bunch of elements first into a QImage-QPainter, and then 
draws the resulting QImage all at once to a screen-QPainter. This 
technique shall avoid flicker.

> I have a messed up knowledge of these subjects and I want a clarity in
> my mind so that I can understand my work and can continue to develop.
> 
> Thanks and Regards
> Dileep

Cheers
Tobias

[0] 
https://cgit.kde.org/scratch/dileepsankhla/okular-gsoc2018-typewriter.git/plain/doc/okular_ui_areas.png
[1] http://doc.qt.io/qt-5/qabstractscrollarea.html#viewport
[2] 
https://www.safaribooksonline.com/library/view/developing-with-pdf/9781449327903
[3] 
https://api.kde.org/frameworks-api/frameworks-apidocs/okular/html/okular_generators.html
[4] http://doc.qt.io/qt-5/qwidget.html#paintEvent


More information about the Okular-devel mailing list