summaryrefslogtreecommitdiff
path: root/draw/draw_edge.c
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-04-07 10:36:36 +0100
committerTor Andersson <tor.andersson@artifex.com>2011-04-07 21:05:29 +0200
commita9560ecb1b1140623d381ef04ede719cc9ff6819 (patch)
tree3f08ea6336db9cf347af1ffa72f643cc9a94caff /draw/draw_edge.c
parent73b82547b63bc1db4412b08d2967ca966fd8cb99 (diff)
downloadmupdf-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.
Diffstat (limited to 'draw/draw_edge.c')
-rw-r--r--draw/draw_edge.c129
1 files changed, 116 insertions, 13 deletions
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);