Fabio D'Urso <[email protected]> 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
pgpONeyOkST4M.pgp
Description: PGP signature
_______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
