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

Adam Reichold adamreichold at myopera.com
Tue Apr 2 09:36:48 PDT 2013


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? (This
could also solve the problem of the annotations being rotated out of the
page bounding box.)

An alternative might be to provide interfaces to get the correctly
transformed boundaries using the frontends. This could then be relied
upon if for example some property of the transform (like the corner to
rotate about) is changed.

This aspect would be emphasized again if the FixedSize flag is to be
implemented in future, because this would imply the need for the
application to tell Poppler about the actual DPI in which to render the
page and the scale factor separately instead of just the pseudo-DPI like
it is now.

Best regards, Adam.

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

More information about the poppler mailing list