[poppler] [PATCHES] Support for the NoRotate annotation flag

Adam Reichold adamreichold at myopera.com
Tue Apr 2 10:59:57 PDT 2013


Hello,

Am 02.04.2013 19:38, schrieb Albert Astals Cid:
> El Dimarts, 2 d'abril de 2013, a les 18:36:48, Adam Reichold va
> escriure:
>> Hello,
>> 
>> Am 31.03.2013 15:16, schrieb Carlos Garcia Campos:
>>> Fabio D'Urso <fabiodurso at hotmail.it> writes:
>>>> Hi,
>>>> 
>>>> the attached patches implement support for the NoRotate
>>>> annotation flag, which tells that the annotation must *not*
>>>> be rotated according to the page orientation or requested
>>>> rendering rotation (more on this later).
>>>> 
>>>> The main reason why I have implemented these patches is 
>>>> https://bugs.kde.org/show_bug.cgi?id=313177, which consists
>>>> in free-text annotations' text being wrongly oriented when
>>>> the page has a /Rotate attribute whose value is different
>>>> than 0. With the NoRotate flag, it will be possible to create
>>>> annotations that always face the viewer, independently from
>>>> the page's /Rotate attribute.
>>>> 
>>>> NoRotate annotations are somewhat tricky, because they are
>>>> never rotated, neither according to the orientation of page,
>>>> nor according to the requested *rendering* rotation. I'm
>>>> attaching a "orientation-examples.pdf" that shows this very
>>>> important aspect. If you open it in acroread and rotate the
>>>> pages, you'll see that NoRotate annotations pivot on their
>>>> top-left corner and always face the viewer. I want to stress
>>>> on this aspect: what you get if you render a page containing
>>>> a NoRotate annotation and then apply a rotation *IS NOT* the 
>>>> same result that you would obtain by directly rendering the
>>>> page at that rotation (see attached image for an example).
>>>> This is the reason why I had to write patch 0004.
>>>> 
>>>> ~ PATCHES 0001 and 0002
>>>> 
>>>> Patch 0001 changes the Gfx::drawAnnot method so that it
>>>> "unrotates" the coordinate system before drawing NoRotate
>>>> annotations. This is the patch that actually implements the
>>>> NoRotate flag, and it works in all cases but rasterized
>>>> postscript output, which is addressed in patch 0004.
>>>> 
>>>> Patch 0002 adds rotation control in poppler-qt4's demo
>>>> application. I've used this patch to quickly test how
>>>> NoRotate annotations behave with different rendering
>>>> rotations.
>>>> 
>>>> @@ -5144,6 +5157,28 @@ void Gfx::drawAnnot(Object *str,
>>>> AnnotBorder *border, AnnotColor *aColor,>> return;
>>>> 
>>>> }
>>>> 
>>>> +  // saves gfx state and automatically restores it on
>>>> return +  GfxStackStateSaver stackStateSaver(this); + +  /*
>>>> If flag NoRotate is set then we need to "unrotate" the
>>>> coordinate system */ +  if ((flags & Annot::flagNoRotate) &&
>>>> state->getRotate() != 0) { +    const double angle_rad =
>>>> state->getRotate() * M_PI / 180; +    const double c =
>>>> cos(angle_rad); +    const double s = sin(angle_rad); + +
>>>> // Rotation around topleft corner (xMin, yMax) +    const
>>>> double unrotateMTX[6] = { +        +c, +s, +        -s, +c, +
>>>> -c*xMin + s*yMax + xMin, -c*yMax - s*xMin + yMax +    }; + +
>>>> state->concatCTM(unrotateMTX[0], unrotateMTX[1],
>>>> unrotateMTX[2], +                     unrotateMTX[3],
>>>> unrotateMTX[4], unrotateMTX[5]); +    out->updateCTM(state,
>>>> unrotateMTX[0], unrotateMTX[1], unrotateMTX[2], +
>>>> unrotateMTX[3], unrotateMTX[4], unrotateMTX[5]); +  } +
>>>> 
>>>> // draw the appearance stream (if there is one) if
>>>> (str->isStream()) {
>>> 
>>> Unfortunately this doesn't work for the cairo backend either,
>>> since state->getRotate() will be 0. In cairo the user typically
>>> does something like:
>>> 
>>> cairo_create() cairo_translate() cairo_scale() cairo_rotate() 
>>> poppler_page_render()
>>> 
>>> And we always pass 0 to displaySlice() since the cairo context
>>> is already transformed.
>> 
>> When implementing this in qpdfview, I spent most of the time
>> figuring out how to correctly transform the annotation boundaries
>> given to me by the qt4 frontend. This is of course not problem in
>> itself, but it aligns with this observation as the applications
>> is bound to use the internal coordinate transformations and needs
>> to correctly recreate their results.
>> 
>> Maybe it would be better to let applications that want to
>> implement this draw those annotations by themselves, hiding
>> Poppler's rendition?
> 
> What's the benefit of everyone doing the same? Wasn't the
> repetition of work why libraries where created?

There is some duplication the current setting as well as the
application has to recreate the internal transformations, but of
course this is much less than actually drawing the annotations. I am
just not sure how well the coupling of these interactive elements with
application behavior through an interface designed to render paginated
content will work. (And how prone it will be to breakage by internal
changes.)

>> (This could also solve the problem of the annotations being
>> rotated out of the page bounding box.)
> 
> I'm sure we can find some other solution for that.

Of course there are other solutions, for example adding an annotation
rendering interface to the frontends the results of which the
application can then compose by itself. My point is basically that if
the interactive elements begin to be more than just
some-more-stuff-on-the-page, the API should probably reflect that.

Best regard, Adam.

> Cheers, Albert _______________________________________________ 
> poppler mailing list poppler at lists.freedesktop.org 
> http://lists.freedesktop.org/mailman/listinfo/poppler
> 


More information about the poppler mailing list