diff options
author | Robin Watts <Robin.Watts@artifex.com> | 2011-04-07 10:36:36 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2011-04-07 21:05:29 +0200 |
commit | a9560ecb1b1140623d381ef04ede719cc9ff6819 (patch) | |
tree | 3f08ea6336db9cf347af1ffa72f643cc9a94caff | |
parent | 73b82547b63bc1db4412b08d2967ca966fd8cb99 (diff) | |
download | mupdf-a9560ecb1b1140623d381ef04ede719cc9ff6819.tar.xz |
Add AA_BITS define to control antialias level of line art.
AA_BITS < 0 => Runtime configurable.
AA_BITS = 0 => No antialiasing
AA_BITS > 0 => At least that many bits of accuracy (to a max of 8).
If unspecified, default is 8, so old behaviour is maintained.
-rw-r--r-- | apps/pdfdraw.c | 9 | ||||
-rw-r--r-- | draw/draw_edge.c | 129 | ||||
-rw-r--r-- | fitz/fitz.h | 3 |
3 files changed, 126 insertions, 15 deletions
diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c index 69a7d3aa..4dd24ff2 100644 --- a/apps/pdfdraw.c +++ b/apps/pdfdraw.c @@ -21,6 +21,7 @@ int showtime = 0; int showmd5 = 0; int savealpha = 0; int uselist = 1; +int alphabits = 8; fz_colorspace *colorspace; fz_glyph_cache *glyphcache; @@ -43,11 +44,12 @@ static void usage(void) fprintf(stderr, "usage: pdfdraw [options] input.pdf [pages]\n" "\t-o -\toutput filename (%%d for page number)\n" - "\t\tsupported formats: pgm, ppm, pam, png\n" + "\t\tsupported formats: pgm, ppm, pam, png, pbm\n" "\t-p -\tpassword\n" "\t-r -\tresolution in dpi (default: 72)\n" "\t-A\tdisable accelerated functions\n" "\t-a\tsave alpha channel (only pam and png)\n" + "\t-b -\tnumber of bits of antialiasing (0 to 8)\n" "\t-g\trender in grayscale\n" "\t-m\tshow timing information\n" "\t-t\tshow text (-tt for xml)\n" @@ -293,7 +295,7 @@ int main(int argc, char **argv) fz_error error; int c; - while ((c = fz_getopt(argc, argv, "o:p:r:R:Aadgmtx5")) != -1) + while ((c = fz_getopt(argc, argv, "o:p:r:R:Aab:dgmtx5")) != -1) { switch (c) { @@ -303,6 +305,7 @@ int main(int argc, char **argv) case 'R': rotation = atof(fz_optarg); break; case 'A': accelerate = 0; break; case 'a': savealpha = 1; break; + case 'b': alphabits = atoi(fz_optarg); break; case 'm': showtime++; break; case 't': showtext++; break; case 'x': showxml++; break; @@ -313,6 +316,8 @@ int main(int argc, char **argv) } } + fz_set_aa_level(alphabits); + if (fz_optind == argc) usage(); diff --git a/draw/draw_edge.c b/draw/draw_edge.c index 9e916555..0dfd9d16 100644 --- a/draw/draw_edge.c +++ b/draw/draw_edge.c @@ -9,7 +9,109 @@ static inline int fz_idiv(int a, int b) return a < 0 ? (a - b + 1) / b : a / b; } -enum { HSCALE = 17, VSCALE = 15, SF = 1 }; +/* Allow the antialiasing level to be varied, both at compile time and at + * runtime. + * + * If AA_BITS is not defined, then we assume constant 8 bits of antialiasing. + * If it is defined to a positive number then we will attempt to provide + * at least that number of bits of accuracy in the antialiasing (to a + * maximum of 8). If it is defined to be 0 then no antialiasing is done. + * If it is defined to be a negative number we will leave the antialiasing + * accuracy as a run time choice. + */ + +#ifndef AA_BITS +#define AA_BITS 8 +#endif + +#if AA_BITS < 0 +static int fz_aa_hscale = 17; +static int fz_aa_vscale = 15; +static int fz_aa_scale = 256; +static int fz_aa_level = 8; +#define AASCALE(c) ((c*fz_aa_scale)>>8) +#define HSCALE fz_aa_hscale +#define VSCALE fz_aa_vscale +#undef AA_BITS +#define AA_BITS 0 +typedef int fz_delta; +#elif AA_BITS == 0 +enum { HSCALE = 1, VSCALE = 1 }; +#define AASCALE(c) (c*255) +#undef AA_BITS +#define AA_BITS 2 +typedef unsigned char fz_delta; +#elif AA_BITS <= 2 +enum { HSCALE = 2, VSCALE = 2 }; +#define AASCALE(c) ((c*255)>>2) +#undef AA_BITS +#define AA_BITS 2 +typedef int fz_delta; +#elif AA_BITS <= 4 +enum { HSCALE = 5, VSCALE = 3 }; +#define AASCALE(c) (c*17) +#undef AA_BITS +#define AA_BITS 4 +typedef unsigned char fz_delta; +#elif AA_BITS <= 6 +enum { HSCALE = 8, VSCALE = 8 }; +#define AASCALE(c) ((c*255)>>6) +#undef AA_BITS +#define AA_BITS 6 +typedef int fz_delta; +#else /* AA_BITS <= 8 */ +enum { HSCALE = 17, VSCALE = 15 }; +#define AASCALE(c) (c) +#undef AA_BITS +#define AA_BITS 8 +typedef unsigned char fz_delta; +#endif + +int fz_get_aa_level(void) +{ +#if AA_BITS <= 0 + return fz_aa_level; +#else + return AA_BITS; +#endif +} + +void fz_set_aa_level(int level) +{ +#if AA_BITS <= 0 + if (level > 6) + { + fz_aa_hscale = 17; + fz_aa_vscale = 15; + fz_aa_level = 8; + } + else if (level > 4) + { + fz_aa_hscale = 8; + fz_aa_vscale = 8; + fz_aa_level = 6; + } + else if (level > 2) + { + fz_aa_hscale = 5; + fz_aa_vscale = 3; + fz_aa_level = 4; + } + else if (level > 0) + { + fz_aa_hscale = 2; + fz_aa_vscale = 2; + fz_aa_level = 2; + } + else + { + fz_aa_hscale = 1; + fz_aa_vscale = 1; + fz_aa_level = 0; + } + fz_aa_scale = 0xFF00 / (fz_aa_hscale * fz_aa_vscale); +#endif +} /* * Global Edge List -- list of straight path segments for scan conversion @@ -393,7 +495,7 @@ advance_ael(fz_ael *ael) */ static inline void -add_span(unsigned char *list, int x0, int x1, int xofs) +add_span(fz_delta *list, int x0, int x1, int xofs) { int x0pix, x0sub; int x1pix, x1sub; @@ -426,7 +528,7 @@ add_span(unsigned char *list, int x0, int x1, int xofs) } static inline void -non_zero_winding(fz_ael *ael, unsigned char *list, int xofs) +non_zero_winding(fz_ael *ael, fz_delta *list, int xofs) { int winding = 0; int x = 0; @@ -442,7 +544,7 @@ non_zero_winding(fz_ael *ael, unsigned char *list, int xofs) } static inline void -even_odd(fz_ael *ael, unsigned char *list, int xofs) +even_odd(fz_ael *ael, fz_delta *list, int xofs) { int even = 0; int x = 0; @@ -458,13 +560,14 @@ even_odd(fz_ael *ael, unsigned char *list, int xofs) } static inline void -undelta(unsigned char *list, int n) +undelta(fz_delta *in, int n) { int d = 0; + unsigned char *out = (unsigned char *)in; while (n--) { - d += *list; - *list++ = d; + d += *in++; + *out++ = AASCALE(d); } } @@ -486,7 +589,7 @@ fz_scan_convert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip, fz_pixmap *dest, unsigned char *color) { fz_error error; - unsigned char *deltas; + fz_delta *deltas; int y, e; int yd, yc; @@ -504,8 +607,8 @@ fz_scan_convert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip, assert(clip.x0 >= xmin); assert(clip.x1 <= xmax); - deltas = fz_malloc(xmax - xmin + 1); - memset(deltas, 0, xmax - xmin + 1); + deltas = fz_malloc((xmax - xmin + 1) * sizeof(fz_delta)); + memset(deltas, 0, (xmax - xmin + 1) * sizeof(fz_delta)); e = 0; y = gel->edges[0].y; @@ -520,8 +623,8 @@ fz_scan_convert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip, if (yd >= clip.y0 && yd < clip.y1) { undelta(deltas, skipx + clipn); - blit(dest, xmin + skipx, yd, deltas + skipx, clipn, color); - memset(deltas, 0, skipx + clipn); + blit(dest, xmin + skipx, yd, (unsigned char *)deltas + skipx, clipn, color); + memset(deltas, 0, (skipx + clipn) * sizeof(fz_delta)); } } yd = yc; @@ -551,7 +654,7 @@ fz_scan_convert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip, if (yd >= clip.y0 && yd < clip.y1) { undelta(deltas, skipx + clipn); - blit(dest, xmin + skipx, yd, deltas + skipx, clipn, color); + blit(dest, xmin + skipx, yd, (unsigned char *)deltas + skipx, clipn, color); } fz_free(deltas); diff --git a/fitz/fitz.h b/fitz/fitz.h index 98047d71..e658481b 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -979,6 +979,9 @@ void fz_free_glyph_cache(fz_glyph_cache *); * Scan converter */ +int fz_get_aa_level(void); +void fz_set_aa_level(int bits); + typedef struct fz_edge_s fz_edge; typedef struct fz_gel_s fz_gel; typedef struct fz_ael_s fz_ael; |