From ea6341ffc4116f7478d82cfba34bccd11103cf7a Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 17 Apr 2016 16:02:57 +0930 Subject: [PATCH] pdftocairo: add -antialias option --- poppler/CairoOutputDev.cc | 24 +++++++++++++++++ poppler/CairoOutputDev.h | 4 ++- utils/pdftocairo.1 | 26 +++++++++++++++++++ utils/pdftocairo.cc | 66 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 112 insertions(+), 8 deletions(-) diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index a4c7a6a..4271eaf 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 0f88778..0035aef 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -265,6 +265,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; } @@ -287,6 +288,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; @@ -339,7 +341,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 83eeba0..075ba64 100644 --- a/utils/pdftocairo.cc +++ b/utils/pdftocairo.cc @@ -105,6 +105,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; @@ -217,6 +218,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"}, @@ -270,6 +273,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; @@ -277,7 +281,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; @@ -596,8 +639,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) { @@ -628,13 +679,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); @@ -913,6 +960,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); -- 2.1.4