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