[poppler] 4 commits - poppler/CairoOutputDev.cc poppler/CairoOutputDev.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Thu Apr 12 11:09:05 PDT 2012


 poppler/CairoOutputDev.cc |  145 ++++++++++++++++++++++++++++++----------------
 poppler/CairoOutputDev.h  |    6 -
 2 files changed, 98 insertions(+), 53 deletions(-)

New commits:
commit 7f0f080277d35f6f2e426ca2a3ff76c2856daeaf
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Apr 10 00:08:49 2012 +0930

    cairo: fix stroke pattern with transparency group
    
    Cairo copy path/append path with device offsets is broken. Use GfxPath
    instead.
    
    Bug 48468

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 8ea4129..32f01d3 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -776,7 +776,7 @@ void CairoOutputDev::fill(GfxState *state) {
     cairo_mask (cairo, mask);
     cairo_restore (cairo);
   } else if (strokePathClip) {
-    fillToStrokePathClip();
+    fillToStrokePathClip(state);
   } else {
     cairo_fill (cairo);
   }
@@ -865,7 +865,7 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx1, Catalog *cat
   cairo_set_source (cairo, pattern);
   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
   if (strokePathClip) {
-    fillToStrokePathClip();
+    fillToStrokePathClip(state);
   } else {
     cairo_fill (cairo);
   }
@@ -1100,8 +1100,7 @@ void CairoOutputDev::eoClip(GfxState *state) {
 void CairoOutputDev::clipToStrokePath(GfxState *state) {
   LOG(printf("clip-to-stroke-path\n"));
   strokePathClip = (StrokePathClip*)gmalloc (sizeof(*strokePathClip));
-  doPath (cairo, state, state->getPath());
-  strokePathClip->path = cairo_copy_path (cairo);
+  strokePathClip->path = state->getPath()->copy();
   cairo_get_matrix (cairo, &strokePathClip->ctm);
   strokePathClip->line_width = cairo_get_line_width (cairo);
   strokePathClip->dash_count = cairo_get_dash_count (cairo);
@@ -1116,7 +1115,7 @@ void CairoOutputDev::clipToStrokePath(GfxState *state) {
   strokePathClip->miter = cairo_get_miter_limit (cairo);
 }
 
-void CairoOutputDev::fillToStrokePathClip() {
+void CairoOutputDev::fillToStrokePathClip(GfxState *state) {
   cairo_save (cairo);
 
   cairo_set_matrix (cairo, &strokePathClip->ctm);
@@ -1126,14 +1125,12 @@ void CairoOutputDev::fillToStrokePathClip() {
   cairo_set_line_cap (cairo, strokePathClip->cap);
   cairo_set_line_join (cairo, strokePathClip->join);
   cairo_set_miter_limit (cairo, strokePathClip->miter);
-
-  cairo_new_path (cairo);
-  cairo_append_path (cairo, strokePathClip->path);
+  doPath (cairo, state, strokePathClip->path);
   cairo_stroke (cairo);
 
   cairo_restore (cairo);
 
-  cairo_path_destroy (strokePathClip->path);
+  delete strokePathClip->path;
   if (strokePathClip->dashes)
     gfree (strokePathClip->dashes);
   gfree (strokePathClip);
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index f0c1666..ae85433 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -273,7 +273,7 @@ protected:
 				     GBool interpolate);
   GBool getStreamData (Stream *str, char **buffer, int *length);
   void setMimeData(Stream *str, Object *ref, cairo_surface_t *image);
-  void fillToStrokePathClip();
+  void fillToStrokePathClip(GfxState *state);
   void alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y);
 
   GfxRGB fill_color, stroke_color;
@@ -286,7 +286,7 @@ protected:
   CairoFont *currentFont;
 
   struct StrokePathClip {
-    cairo_path_t *path;
+    GfxPath *path;
     cairo_matrix_t ctm;
     double line_width;
     double *dashes;
commit 5ea305c3924cead302092378ab67300c3099afd9
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 8 23:11:30 2012 +0930

    cairo: only align stroke coords for horizontal and vertical lines
    
    Bug 48318

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index df2be51..8ea4129 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -640,48 +640,90 @@ void CairoOutputDev::updateFont(GfxState *state) {
   cairo_set_font_matrix (cairo, &matrix);
 }
 
-void CairoOutputDev::alignStrokeCoords(double *x, double *y)
+/* Tolerance in pixels for checking if strokes are horizontal or vertical
+ * lines in device space */
+#define STROKE_COORD_TOLERANCE 0.5
+
+/* Align stroke coordinate i if the point is the start or end of a
+ * horizontal or vertical line */
+void CairoOutputDev::alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y)
 {
-  /* see http://www.cairographics.org/FAQ/#sharp_lines */
-  cairo_user_to_device (cairo, x, y);
-  *x = floor(*x) + 0.5;
-  *y = floor(*y) + 0.5;
-  cairo_device_to_user (cairo, x, y);
+  double x1, y1, x2, y2;
+  GBool align = gFalse;
+
+  x1 = subpath->getX(i);
+  y1 = subpath->getY(i);
+  cairo_user_to_device (cairo, &x1, &y1);
+
+  // Does the current coord and prev coord form a horiz or vert line?
+  if (i > 0 && !subpath->getCurve(i - 1)) {
+    x2 = subpath->getX(i - 1);
+    y2 = subpath->getY(i - 1);
+    cairo_user_to_device (cairo, &x2, &y2);
+    if (fabs(x2 - x1) < STROKE_COORD_TOLERANCE || fabs(y2 - y1) < STROKE_COORD_TOLERANCE)
+      align = gTrue;
+  }
+
+  // Does the current coord and next coord form a horiz or vert line?
+  if (i < subpath->getNumPoints() - 1 && !subpath->getCurve(i + 1)) {
+    x2 = subpath->getX(i + 1);
+    y2 = subpath->getY(i + 1);
+    cairo_user_to_device (cairo, &x2, &y2);
+    if (fabs(x2 - x1) < STROKE_COORD_TOLERANCE || fabs(y2 - y1) < STROKE_COORD_TOLERANCE)
+      align = gTrue;
+  }
+
+  *x = subpath->getX(i);
+  *y = subpath->getY(i);
+  if (align) {
+    /* see http://www.cairographics.org/FAQ/#sharp_lines */
+    cairo_user_to_device (cairo, x, y);
+    *x = floor(*x) + 0.5;
+    *y = floor(*y) + 0.5;
+    cairo_device_to_user (cairo, x, y);
+  }
 }
 
+#undef STROKE_COORD_TOLERANCE
+
 void CairoOutputDev::doPath(cairo_t *cairo, GfxState *state, GfxPath *path) {
   GfxSubpath *subpath;
   int i, j;
+  double x, y;
   cairo_new_path (cairo);
   for (i = 0; i < path->getNumSubpaths(); ++i) {
     subpath = path->getSubpath(i);
     if (subpath->getNumPoints() > 0) {
       if (align_stroke_coords) {
-	double x = subpath->getX(0);
-	double y = subpath->getY(0);
-	alignStrokeCoords(&x, &y);
-	cairo_move_to (cairo, x, y);
+        alignStrokeCoords(subpath, 0, &x, &y);
       } else {
-	cairo_move_to (cairo, subpath->getX(0), subpath->getY(0));
+        x = subpath->getX(0);
+        y = subpath->getY(0);
       }
+      cairo_move_to (cairo, x, y);
       j = 1;
       while (j < subpath->getNumPoints()) {
 	if (subpath->getCurve(j)) {
+	  if (align_stroke_coords) {
+            alignStrokeCoords(subpath, j + 2, &x, &y);
+          } else {
+            x = subpath->getX(j+2);
+            y = subpath->getY(j+2);
+          }
 	  cairo_curve_to( cairo,
 			  subpath->getX(j), subpath->getY(j),
 			  subpath->getX(j+1), subpath->getY(j+1),
-			  subpath->getX(j+2), subpath->getY(j+2));
+			  x, y);
 
 	  j += 3;
 	} else {
 	  if (align_stroke_coords) {
-	    double x = subpath->getX(j);
-	    double y = subpath->getY(j);
-	    alignStrokeCoords(&x, &y);
-	    cairo_line_to (cairo, x, y);
-	  } else {
-	    cairo_line_to (cairo, subpath->getX(j), subpath->getY(j));
-	  }
+            alignStrokeCoords(subpath, j, &x, &y);
+          } else {
+            x = subpath->getX(j);
+            y = subpath->getY(j);
+          }
+          cairo_line_to (cairo, x, y);
 	  ++j;
 	}
       }
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 873dd43..f0c1666 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -274,7 +274,7 @@ protected:
   GBool getStreamData (Stream *str, char **buffer, int *length);
   void setMimeData(Stream *str, Object *ref, cairo_surface_t *image);
   void fillToStrokePathClip();
-  void alignStrokeCoords(double *x, double *y);
+  void alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y);
 
   GfxRGB fill_color, stroke_color;
   cairo_pattern_t *fill_pattern, *stroke_pattern;
commit 8414d8f621b8abb018e80f2255cfb511a1e558d4
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Apr 9 12:08:20 2012 +0930

    cairo: ensure 0 width lines with stroke_adjust are aligned
    
    Previously the code path for 0 width lines ignored the stroke_adjust
    setting. Rearrange the code so the code path for stroke_adjust == TRUE
    is performed first (this will also set 0 width lines to 1 pixel wide).

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index fa29146..df2be51 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -417,9 +417,25 @@ void CairoOutputDev::updateMiterLimit(GfxState *state) {
 void CairoOutputDev::updateLineWidth(GfxState *state) {
   LOG(printf ("line width: %f\n", state->getLineWidth()));
   adjusted_stroke_width = gFalse;
-  if (state->getLineWidth() == 0.0) {
-    /* find out how big pixels (device unit) are in the x and y directions
-     * choose the smaller of the two as our line width */
+  double width = state->getLineWidth();
+  if (stroke_adjust && !printing) {
+    double x, y;
+    x = y = width;
+
+    /* find out line width in device units */
+    cairo_user_to_device_distance(cairo, &x, &y);
+    if (fabs(x) <= 1.0 && fabs(y) <= 1.0) {
+      /* adjust width to at least one device pixel */
+      x = y = 1.0;
+      cairo_device_to_user_distance(cairo, &x, &y);
+      width = MIN(fabs(x),fabs(y));
+      adjusted_stroke_width = gTrue;
+    }
+  } else if (width == 0.0) {
+    /* Cairo does not support 0 line width == 1 device pixel. Find out
+     * how big pixels (device unit) are in the x and y
+     * directions. Choose the smaller of the two as our line width.
+     */
     double x = 1.0, y = 1.0;
     if (printing) {
       // assume printer pixel size is 1/600 inch
@@ -427,25 +443,9 @@ void CairoOutputDev::updateLineWidth(GfxState *state) {
       y = 72.0/600;
     }
     cairo_device_to_user_distance(cairo, &x, &y);
-    cairo_set_line_width (cairo, MIN(fabs(x),fabs(y)));
-  } else {
-    double width = state->getLineWidth();
-    if (stroke_adjust && !printing) {
-      double x, y;
-      x = y = width;
-
-      /* find out line width in device units */
-      cairo_user_to_device_distance(cairo, &x, &y);
-      if (fabs(x) <= 1.0 && fabs(y) <= 1.0) {
-	/* adjust width to at least one device pixel */
-	x = y = 1.0;
-	cairo_device_to_user_distance(cairo, &x, &y);
-	width = MIN(fabs(x),fabs(y));
-	adjusted_stroke_width = gTrue;
-      }
-    }
-    cairo_set_line_width (cairo, width);
+    width = MIN(fabs(x),fabs(y));
   }
+  cairo_set_line_width (cairo, width);
   if (cairo_shape)
     cairo_set_line_width (cairo_shape, cairo_get_line_width (cairo));
 }
commit af1a84eb90656de68bb14f2c4ae4f813c51bc3a3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Apr 9 17:17:29 2012 +0930

    cairo: fix paintTransparencyGroup when both mask and fill opacity are required
    
    Bug 48453

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 22fdaca..fa29146 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1460,11 +1460,17 @@ void CairoOutputDev::paintTransparencyGroup(GfxState * /*state*/, double * /*bbo
     if (status)
       printf("BAD status: %s\n", cairo_status_to_string(status));
   } else {
+    if (fill_opacity < 1.0) {
+      cairo_push_group(cairo);
+    }
     cairo_save(cairo);
     cairo_set_matrix(cairo, &mask_matrix);
     cairo_mask(cairo, mask);
     cairo_restore(cairo);
-
+    if (fill_opacity < 1.0) {
+      cairo_pop_group_to_source(cairo);
+      cairo_paint_with_alpha (cairo, fill_opacity);
+    }
     cairo_pattern_destroy(mask);
     mask = NULL;
   }


More information about the poppler mailing list