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

Carlos Garcia Campos carlosgc at gnome.org
Sun Mar 31 06:16:53 PDT 2013


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.

-- 
Carlos Garcia Campos
PGP key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x523E6462
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/poppler/attachments/20130331/b4e2476a/attachment.pgp>


More information about the poppler mailing list