[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