[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h utils/pdftocairo.1 utils/pdftocairo.cc

Adrian Johnson ajohnson at kemper.freedesktop.org
Fri May 20 09:55:13 UTC 2016


 poppler/CairoOutputDev.cc |   24 ++++++++++++++++
 poppler/CairoOutputDev.h  |    4 ++
 utils/pdftocairo.1        |   26 ++++++++++++++++++
 utils/pdftocairo.cc       |   66 +++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 112 insertions(+), 8 deletions(-)

New commits:
commit 853e94995255591b35d9bdbeb0174476838097c0
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Apr 17 16:02:57 2016 +0930

    pdftocairo: add -antialias option
    
    Bug 94977

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index b0987b3..9f892b2 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -206,6 +206,7 @@ void CairoOutputDev::setCairo(cairo_t *cairo)
 	/* save the initial matrix so that we can use it for type3 fonts. */
 	//XXX: is this sufficient? could we miss changes to the matrix somehow?
 	cairo_get_matrix(cairo, &orig_matrix);
+	setAntialias(cairo, antialias);
   } else {
     this->cairo = NULL;
     this->cairo_shape = NULL;
@@ -228,6 +229,26 @@ void CairoOutputDev::setTextPage(TextPage *text)
   }
 }
 
+void CairoOutputDev::setAntialias(cairo_antialias_t antialias)
+{
+  this->antialias = antialias;
+  if (cairo)
+    setAntialias (cairo, antialias);
+  if (cairo_shape)
+    setAntialias (cairo_shape, antialias);
+}
+
+void CairoOutputDev::setAntialias(cairo_t *cr, cairo_antialias_t antialias)
+{
+  cairo_font_options_t *font_options;
+  cairo_set_antialias (cairo, antialias);
+  font_options = cairo_font_options_create ();
+  cairo_get_font_options (cr, font_options);
+  cairo_font_options_set_antialias (font_options, antialias);
+  cairo_set_font_options (cr, font_options);
+  cairo_font_options_destroy (font_options);
+}
+
 void CairoOutputDev::startDoc(PDFDoc *docA,
 			      CairoFontEngine *parentFontEngine) {
   doc = docA;
@@ -913,6 +934,7 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat
   old_cairo = cairo;
   cairo = cairo_create (surface);
   cairo_surface_destroy (surface);
+  setAntialias(cairo, antialias);
   cairo_scale (cairo, surface_width / width, surface_height / height);
 
   box.x1 = bbox[0]; box.y1 = bbox[1];
@@ -1611,6 +1633,7 @@ void CairoOutputDev::beginTransparencyGroup(GfxState * /*state*/, double * /*bbo
       cairo_surface_t *cairo_shape_surface = cairo_surface_create_similar_clip (cairo, CAIRO_CONTENT_ALPHA);
       cairo_shape = cairo_create (cairo_shape_surface);
       cairo_surface_destroy (cairo_shape_surface);
+      setAntialias(cairo_shape, antialias);
 
       /* the color doesn't matter as long as it is opaque */
       cairo_set_source_rgb (cairo_shape, 0, 0, 0);
@@ -1765,6 +1788,7 @@ void CairoOutputDev::setSoftMask(GfxState * state, double * bbox, GBool alpha,
 
     cairo_surface_t *source = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
     cairo_t *maskCtx = cairo_create(source);
+    setAntialias(maskCtx, antialias);
 
     //XXX: hopefully this uses the correct color space */
     if (!alpha && groupColorSpaceStack->cs) {
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 103a326..3a6dbfa 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -266,6 +266,7 @@ public:
   void setCairo (cairo_t *cr);
   void setTextPage (TextPage *text);
   void setPrinting (GBool printing) { this->printing = printing; needFontUpdate = gTrue; }
+  void setAntialias(cairo_antialias_t antialias);
 
   void setInType3Char(GBool inType3Char) { this->inType3Char = inType3Char; }
   void getType3GlyphWidth (double *wx, double *wy) { *wx = t3_glyph_wx; *wy = t3_glyph_wy; }
@@ -288,6 +289,7 @@ protected:
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
   GBool setMimeDataForJBIG2Globals (Stream *str, cairo_surface_t *image);
 #endif
+  void setAntialias(cairo_t *cr, cairo_antialias_t antialias);
 
   GfxRGB fill_color, stroke_color;
   cairo_pattern_t *fill_pattern, *stroke_pattern;
@@ -340,7 +342,7 @@ protected:
   double t3_glyph_wx, t3_glyph_wy;
   GBool t3_glyph_has_bbox;
   double t3_glyph_bbox[4];
-
+  cairo_antialias_t antialias;
   GBool prescaleImages;
 
   TextPage *text;		// text for the current page
diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1
index 2211da7..5e30adf 100644
--- a/utils/pdftocairo.1
+++ b/utils/pdftocairo.1
@@ -167,6 +167,32 @@ Generate a monochrome file (PNG and TIFF only).
 .B \-gray
 Generate a grayscale file (PNG, JPEG, and TIFF only).
 .TP
+.B \-antialias
+Set the cairo antialias option used for text and drawing in image files (or rasterized regions in vector output). The options are:
+.RS
+.TP
+.B default
+Use the default antialiasing for the target device. This is the default setting if \-antialias is not used.
+.TP
+.B none
+Antialiasing is disabled.
+.TP
+.B gray
+Perform single-color antialiasing using shades of gray.
+.TP
+.B subpixel
+Perform antialiasing by taking advantage of the order of subpixel elements on devices such as LCD.
+.TP
+.B fast
+Hint that the backend should perform some antialiasing but prefer speed over quality.
+.TP
+.B good
+The backend should balance quality against performance.
+.TP
+.B best
+Hint that the backend should render at the highest quality, sacrificing speed if necessary.
+.RE
+.TP
 .B \-transp
 Use a transparent page color instead of white (PNG and TIFF only).
 .TP
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index 71c60ef..906a5a1 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -106,6 +106,7 @@ static GBool useCropBox = gFalse;
 static GBool mono = gFalse;
 static GBool gray = gFalse;
 static GBool transp = gFalse;
+static GooString antialias;
 static GooString icc;
 
 static GBool level2 = gFalse;
@@ -218,6 +219,8 @@ static const ArgDesc argDesc[] = {
    "generate a grayscale image file (PNG, JPEG)"},
   {"-transp",   argFlag,     &transp,          0,
    "use a transparent background instead of white (PNG)"},
+  {"-antialias",   argGooString,     &antialias,          0,
+   "set cairo antialias option"},
 #if USE_CMS
   {"-icc",   argGooString,     &icc,          0,
    "ICC color profile to use"},
@@ -271,6 +274,7 @@ static  cairo_surface_t *surface;
 static  GBool printing;
 static  FILE *output_file;
 static GBool usePDFPageSize;
+static cairo_antialias_t antialiasEnum = CAIRO_ANTIALIAS_DEFAULT;
 
 #if USE_CMS
 static unsigned char *icc_data;
@@ -278,7 +282,46 @@ static int icc_data_size;
 static cmsHPROFILE profile;
 #endif
 
-void writePageImage(GooString *filename)
+struct AntiliasOption
+{
+  const char *name;
+  cairo_antialias_t value;
+};
+
+static const AntiliasOption antialiasOptions[] =
+{
+  { "default",  CAIRO_ANTIALIAS_DEFAULT },
+  { "none",     CAIRO_ANTIALIAS_NONE },
+  { "gray",     CAIRO_ANTIALIAS_GRAY },
+  { "subpixel", CAIRO_ANTIALIAS_SUBPIXEL },
+  { "fast",     CAIRO_ANTIALIAS_FAST },
+  { "good",     CAIRO_ANTIALIAS_GOOD },
+  { "best",     CAIRO_ANTIALIAS_BEST },
+  { NULL,       CAIRO_ANTIALIAS_DEFAULT },
+};
+
+static GBool parseAntialiasOption(GooString *antialias, cairo_antialias_t *antialiasEnum)
+{
+  const AntiliasOption *option = antialiasOptions;
+  while (option->name) {
+    if (antialias->cmp(option->name) == 0) {
+      *antialiasEnum = option->value;
+      return gTrue;
+    }
+    option++;
+  }
+
+  fprintf(stderr, "Error: Invalid antialias option \"%s\"\n", antialias->getCString());
+  fprintf(stderr, "Valid options are:\n");
+  option = antialiasOptions;
+  while (option->name) {
+    fprintf(stderr, "  %s\n", option->name);
+    option++;
+  }
+  return gFalse;
+}
+
+static void writePageImage(GooString *filename)
 {
   ImgWriter *writer = 0;
   FILE *file;
@@ -597,8 +640,16 @@ static void renderPage(PDFDoc *doc, CairoOutputDev *cairoOut, int pg,
   cairo_matrix_t m;
 
   cr = cairo_create(surface);
+
+  if (!printing && !transp) {
+    cairo_set_source_rgb (cr, 1,1,1);
+    cairo_paint (cr);
+    cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
+  }
+
   cairoOut->setCairo(cr);
   cairoOut->setPrinting(printing);
+  cairoOut->setAntialias(antialiasEnum);
 
   cairo_save(cr);
   if (ps && output_w > output_h) {
@@ -629,13 +680,9 @@ static void renderPage(PDFDoc *doc, CairoOutputDev *cairoOut, int pg,
   cairo_restore(cr);
   cairoOut->setCairo(NULL);
 
-  // Blend onto white page
   if (!printing && !transp) {
-    cairo_save(cr);
-    cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
-    cairo_set_source_rgb(cr, 1, 1, 1);
-    cairo_paint(cr);
-    cairo_restore(cr);
+    cairo_pop_group_to_source (cr);
+    cairo_paint (cr);
   }
 
   status = cairo_status(cr);
@@ -914,6 +961,11 @@ int main(int argc, char *argv[]) {
     exit(99);
   }
 
+  if (antialias.getLength() > 0) {
+    if (!parseAntialiasOption(&antialias, &antialiasEnum))
+      exit(99);
+  }
+
   if (transp && !(png || tiff)) {
     fprintf(stderr, "Error: -transp may only be used with png or tiff output.\n");
     exit(99);


More information about the poppler mailing list