summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pdfdraw.c67
-rw-r--r--draw/imagedraw.c123
-rw-r--r--draw/imageunpack.c2
-rw-r--r--draw/pathscan.c54
-rw-r--r--draw/porterduff.c53
-rw-r--r--fitz/dev_draw.c15
-rw-r--r--fitz/fitz_draw.h4
7 files changed, 289 insertions, 29 deletions
diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c
index 1f93f777..4a4117fe 100644
--- a/apps/pdfdraw.c
+++ b/apps/pdfdraw.c
@@ -14,7 +14,7 @@
#include <sys/time.h>
#endif
-enum { DRAWPNM, DRAWTXT, DRAWXML };
+enum { DRAWPNM, DRAWPGM, DRAWTXT, DRAWXML };
struct benchmark
{
@@ -59,6 +59,7 @@ static void drawusage(void)
" -o -\tpattern (%%d for page number) for output file\n"
" -r -\tresolution in dpi\n"
" -m\tprint benchmark results\n"
+ " -g\toutput a pgm rather than a pnm\n"
" -s\tprint MD5 checksum of page pixel data\n"
" -t\ttext extraction mode\n"
" -x\txml trace mode\n"
@@ -139,7 +140,7 @@ static void drawfreepage(void)
}
}
-static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *drawtimes)
+static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *drawtimes, int greyscale)
{
static int fd = -1;
fz_error error;
@@ -182,11 +183,18 @@ static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *
die(fz_throw("ioerror: could not create raster file '%s'", name));
}
- sprintf(pnmhdr, "P6\n%d %d\n255\n", w, h);
+ if (greyscale)
+ {
+ sprintf(pnmhdr, "P5\n%d %d\n255\n", w, h);
+ }
+ else
+ {
+ sprintf(pnmhdr, "P6\n%d %d\n255\n", w, h);
+ }
write(fd, pnmhdr, strlen(pnmhdr));
}
- pix = fz_newpixmap(pdf_devicergb, bbox.x0, bbox.y0, w, bh);
+ pix = fz_newpixmap((greyscale ? pdf_devicegray : pdf_devicergb), bbox.x0, bbox.y0, w, bh);
fz_clearpixmap(pix, 0xFF);
memset(pix->samples, 0xff, pix->h * pix->w * pix->n);
@@ -204,27 +212,47 @@ static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark *
die(fz_rethrow(error, "cannot draw page %d in PDF file '%s'", pagenum, basename));
fz_freedevice(dev);
+ if (checksum)
+ fz_md5update(&digest, pix->samples, pix->h * pix->w * pix->n);
if (drawpattern)
{
- for (y = 0; y < pix->h; y++)
+ unsigned char *src = pix->samples;
+ if (greyscale)
{
- unsigned char *src = pix->samples + y * pix->w * 4;
- unsigned char *dst = src;
+ for (y = pix->h; y > 0; y--)
+ {
+ unsigned char *dst = src;
+
+ for (x = pix->w; x > 0; x--)
+ {
+ src++;
+ *dst++ = *src++;
+ }
+ dst -= pix->w;
- for (x = 0; x < pix->w; x++)
+ write(fd, dst, pix->w);
+ }
+ }
+ else
+ {
+ for (y = pix->h; y > 0; y--)
{
- dst[x * 3 + 0] = src[x * 4 + 1];
- dst[x * 3 + 1] = src[x * 4 + 2];
- dst[x * 3 + 2] = src[x * 4 + 3];
+ unsigned char *dst = src;
+
+ for (x = pix->w; x > 0; x--)
+ {
+ src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ }
+ dst -= pix->w * 3;
+
+ write(fd, dst, pix->w * 3);
}
-
- write(fd, dst, pix->w * 3);
}
}
- if (checksum)
- fz_md5update(&digest, pix->samples, pix->h * pix->w * 4);
-
pix->y += bh;
if (pix->y + pix->h > bbox.y1)
pix->h = bbox.y1 - pix->y;
@@ -374,7 +402,8 @@ static void drawpages(char *pagelist)
{
switch (drawmode)
{
- case DRAWPNM: drawpnm(page, &loadtimes, &drawtimes); break;
+ case DRAWPNM: drawpnm(page, &loadtimes, &drawtimes, 0); break;
+ case DRAWPGM: drawpnm(page, &loadtimes, &drawtimes, 1); break;
case DRAWTXT: drawtxt(page, &loadtimes); break;
case DRAWXML: drawxml(page); break;
}
@@ -411,7 +440,7 @@ int main(int argc, char **argv)
fz_cpudetect();
fz_accelerate();
- while ((c = fz_getopt(argc, argv, "b:p:o:r:txms")) != -1)
+ while ((c = fz_getopt(argc, argv, "b:p:o:r:gtxms")) != -1)
{
switch (c)
{
@@ -419,6 +448,7 @@ int main(int argc, char **argv)
case 'p': password = fz_optarg; break;
case 'o': drawpattern = fz_optarg; break;
case 'r': drawzoom = atof(fz_optarg) / 72; break;
+ case 'g': drawmode = DRAWPGM; break;
case 't': drawmode = DRAWTXT; break;
case 'x': drawmode = DRAWXML; break;
case 'm': benchmark = 1; break;
@@ -464,4 +494,3 @@ int main(int argc, char **argv)
return 0;
}
-
diff --git a/draw/imagedraw.c b/draw/imagedraw.c
index 9f6d93bf..81d2bb05 100644
--- a/draw/imagedraw.c
+++ b/draw/imagedraw.c
@@ -22,6 +22,16 @@ getargb(byte *s, int w, int h, int u, int v)
return s + ((w * v + u) << 2);
}
+static inline byte *
+getag(byte *s, int w, int h, int u, int v)
+{
+ if (u < 0) u = 0;
+ if (v < 0) v = 0;
+ if (u >= w) u = w - 1;
+ if (v >= h) v = h - 1;
+ return s + ((w * v + u) << 1);
+}
+
static inline int
getcolor(byte *s, int w, int h, int n, int u, int v, int k)
{
@@ -39,6 +49,13 @@ lerp(int a, int b, int t)
}
static inline void
+lerpag(byte *dst, byte *a, byte *b, int t)
+{
+ dst[0] = lerp(a[0], b[0], t);
+ dst[1] = lerp(a[1], b[1], t);
+}
+
+static inline void
lerpargb(byte *dst, byte *a, byte *b, int t)
{
dst[0] = lerp(a[0], b[0], t);
@@ -64,6 +81,24 @@ samplemask(byte *s, int w, int h, int u, int v)
}
static inline void
+sampleag(byte *s, int w, int h, int u, int v, byte *out)
+{
+ byte ab[4];
+ byte cd[4];
+ int ui = u >> 16;
+ int vi = v >> 16;
+ int ud = u & 0xFFFF;
+ int vd = v & 0xFFFF;
+ byte *a = getag(s, w, h, ui, vi);
+ byte *b = getag(s, w, h, ui+1, vi);
+ byte *c = getag(s, w, h, ui, vi+1);
+ byte *d = getag(s, w, h, ui+1, vi+1);
+ lerpag(ab, a, b, ud);
+ lerpag(cd, c, d, ud);
+ lerpag(out, ab, cd, vd);
+}
+
+static inline void
sampleargb(byte *s, int w, int h, int u, int v, byte *out)
{
byte ab[4];
@@ -129,6 +164,35 @@ img_1o1(byte * restrict src, byte cov, int len, byte * restrict dst,
}
static void
+img_2o2(byte * restrict src, byte cov, int len, byte * restrict dst,
+ fz_pixmap *image, int u, int v, int fa, int fb)
+{
+ byte *samples = image->samples;
+ int w = image->w;
+ int h = image->h;
+ byte ag[2];
+
+ while (len--)
+ {
+ int sa;
+ cov += *src; *src = 0; src++;
+ if (cov != 0)
+ {
+ sampleag(samples, w, h, u, v, ag);
+ sa = FZ_COMBINE(FZ_EXPAND(ag[0]), FZ_EXPAND(cov));
+ if (sa != 0)
+ {
+ dst[0] = FZ_BLEND(255, dst[0], sa);
+ dst[1] = FZ_BLEND(ag[1], dst[1], sa);
+ }
+ }
+ dst += 2;
+ u += fa;
+ v += fb;
+ }
+}
+
+static void
img_4o4(byte * restrict src, byte cov, int len, byte * restrict dst,
fz_pixmap *image, int u, int v, int fa, int fb)
{
@@ -160,6 +224,63 @@ img_4o4(byte * restrict src, byte cov, int len, byte * restrict dst,
}
static void
+img_w2i1o2(byte *ag, byte * restrict src, byte cov, int len, byte * restrict dst,
+ fz_pixmap *image, int u, int v, int fa, int fb)
+{
+ byte *samples = image->samples;
+ int w = image->w;
+ int h = image->h;
+ int alpha = FZ_EXPAND(ag[0]);
+ byte g = ag[1];
+
+ if (alpha == 0)
+ return;
+ if (alpha != 256)
+ {
+ while (len--)
+ {
+ int ca;
+ cov += *src; *src = 0; src++;
+ if (cov != 0)
+ {
+ ca = samplemask(samples, w, h, u, v);
+ ca =FZ_COMBINE(FZ_EXPAND(cov),FZ_EXPAND(ca));
+ ca = FZ_COMBINE(ca, alpha);
+ if (ca != 0)
+ {
+ dst[0] = FZ_BLEND(255, dst[0], ca);
+ dst[1] = FZ_BLEND(g, dst[1], ca);
+ }
+ }
+ dst += 2;
+ u += fa;
+ v += fb;
+ }
+ }
+ else
+ {
+ while (len--)
+ {
+ int ca;
+ cov += *src; *src = 0; src++;
+ if (cov != 0)
+ {
+ ca = samplemask(samples, w, h, u, v);
+ ca =FZ_COMBINE(FZ_EXPAND(cov),FZ_EXPAND(ca));
+ if (ca != 0)
+ {
+ dst[0] = FZ_BLEND(255, dst[0], ca);
+ dst[1] = FZ_BLEND(g, dst[1], ca);
+ }
+ }
+ dst += 2;
+ u += fa;
+ v += fb;
+ }
+ }
+}
+
+static void
img_w4i1o4(byte *argb, byte * restrict src, byte cov, int len, byte * restrict dst,
fz_pixmap *image, int u, int v, int fa, int fb)
{
@@ -223,5 +344,7 @@ img_w4i1o4(byte *argb, byte * restrict src, byte cov, int len, byte * restrict d
}
void (*fz_img_1o1)(byte*, byte, int, byte*, fz_pixmap *image, int u, int v, int fa, int fb) = img_1o1;
+void (*fz_img_2o2)(byte*, byte, int, byte*, fz_pixmap *image, int u, int v, int fa, int fb) = img_2o2;
void (*fz_img_4o4)(byte*, byte, int, byte*, fz_pixmap *image, int u, int v, int fa, int fb) = img_4o4;
+void (*fz_img_w2i1o2)(byte*, byte*, byte, int, byte*, fz_pixmap *image, int u, int v, int fa, int fb) = img_w2i1o2;
void (*fz_img_w4i1o4)(byte*, byte*, byte, int, byte*, fz_pixmap *image, int u, int v, int fa, int fb) = img_w4i1o4;
diff --git a/draw/imageunpack.c b/draw/imageunpack.c
index 4c9923fd..4e876092 100644
--- a/draw/imageunpack.c
+++ b/draw/imageunpack.c
@@ -28,7 +28,7 @@ static void decodetile(fz_pixmap *pix, int skip, float *decode)
min[i] = decode[(i - skip) * 2] * 255;
max[i] = decode[(i - skip) * 2 + 1] * 255;
sub[i] = max[i] - min[i];
- needed |= (min[i] != 0) | (max[i] != 255);
+ needed |= (min[i] != 0) | (max[i] != 255);
justinvert &= min[i] == 255 && max[i] == 0 && sub[i] == -255;
}
diff --git a/draw/pathscan.c b/draw/pathscan.c
index 5a656144..319cfeb1 100644
--- a/draw/pathscan.c
+++ b/draw/pathscan.c
@@ -422,7 +422,7 @@ static inline void toalpha(unsigned char *list, int n)
static inline void blit(fz_pixmap *pix, int x, int y,
unsigned char *list, int skipx, int len,
- unsigned char *argb, fz_pixmap *image, fz_matrix *invmat)
+ unsigned char *color, fz_pixmap *image, fz_matrix *invmat)
{
unsigned char *dst;
unsigned char cov;
@@ -443,17 +443,61 @@ static inline void blit(fz_pixmap *pix, int x, int y,
int v = (invmat->b * (x + 0.5f) + invmat->d * (y + 0.5f) + invmat->f) * 65536;
int fa = invmat->a * 65536;
int fb = invmat->b * 65536;
- if (argb)
- fz_img_w4i1o4(argb, list, cov, len, dst, image, u, v, fa, fb);
+ assert(image->n == pix->n);
+ if (color)
+ {
+ switch (pix->n)
+ {
+ case 2:
+ fz_img_w2i1o2(color, list, cov, len, dst, image, u, v, fa, fb);
+ break;
+ case 4:
+ fz_img_w4i1o4(color, list, cov, len, dst, image, u, v, fa, fb);
+ break;
+ default:
+ assert("Write fz_img_wni1on" != NULL);
+ //fz_img_wni1on(color, list, cov, len, dst, image, u, v, fa, fb);
+ break;
+ }
+ }
else if (image->colorspace)
+ {
+ assert(image->colorspace->n == image->n-1);
+ switch (pix->n)
+ {
+ case 2:
+ fz_img_2o2(list, cov, len, dst, image, u, v, fa, fb);
+ break;
+ case 4:
fz_img_4o4(list, cov, len, dst, image, u, v, fa, fb);
+ break;
+ default:
+ assert("Write fz_img_non" != NULL);
+ //fz_img_non(list, cov, len, dst, image, u, v, fa, fb);
+ break;
+ }
+ }
else
fz_img_1o1(list, cov, len, dst, image, u, v, fa, fb);
}
else
{
- if (argb)
- fz_path_w4i1o4(argb, list, cov, len, dst);
+ if (color)
+ {
+ switch (pix->n)
+ {
+ case 2:
+ fz_path_w2i1o2(color, list, cov, len, dst);
+ break;
+ case 4:
+ fz_path_w4i1o4(color, list, cov, len, dst);
+ break;
+ default:
+ assert("Write fz_path_wni1on" != NULL);
+ //fz_path_wni1on(color, list, cov, len, dst);
+ break;
+ }
+ }
else
fz_path_1o1(list, cov, len, dst);
}
diff --git a/draw/porterduff.c b/draw/porterduff.c
index 34d5cee8..4616e3fa 100644
--- a/draw/porterduff.c
+++ b/draw/porterduff.c
@@ -20,7 +20,8 @@ duff_non(byte * restrict sp, int sw, int sn, byte * restrict dp, int dw, int w0,
{
/* RJW: Alpha handling suspicious here; sp[0] counts twice */
int sa = FZ_EXPAND(sp[0]);
- for (k = 0; k < sn; k++)
+ dp[0] = FZ_BLEND(255, dp[k], sa);
+ for (k = 1; k < sn; k++)
{
dp[k] = FZ_BLEND(sp[k], dp[k], sa);
}
@@ -47,7 +48,8 @@ duff_nimon(byte * restrict sp, int sw, int sn, byte * restrict mp, int mw, int m
{
/* TODO: validate this */
int ma = FZ_COMBINE(FZ_EXPAND(mp[0]), FZ_EXPAND(sp[0]));
- for (k = 0; k < sn; k++)
+ dp[k] = FZ_BLEND(255, dp[k], ma);
+ for (k = 1; k < sn; k++)
{
dp[k] = FZ_BLEND(sp[k], dp[k], ma);
}
@@ -93,7 +95,7 @@ duff_4o4(byte *sp, int sw, byte *dp, int dw, int w0, int h)
while (w--)
{
int alpha = FZ_EXPAND(sp[0]);
- dp[0] = FZ_BLEND(sp[0], dp[0], alpha);
+ dp[0] = FZ_BLEND(255, dp[0], alpha);
dp[1] = FZ_BLEND(sp[1], dp[1], alpha);
dp[2] = FZ_BLEND(sp[2], dp[2], alpha);
dp[3] = FZ_BLEND(sp[3], dp[3], alpha);
@@ -174,12 +176,30 @@ path_1o1(byte * restrict src, byte cov, int len, byte * restrict dst)
}
static void
+path_w2i1o2(byte * restrict ag, byte * restrict src, byte cov, int len, byte * restrict dst)
+{
+ int alpha = FZ_EXPAND(ag[0]);
+ byte g = ag[1];
+
+ while (len--)
+ {
+ int ca;
+ cov += *src; *src = 0; src++;
+ ca = FZ_COMBINE(FZ_EXPAND(cov), alpha);
+ dst[0] = FZ_BLEND(255, dst[0], ca);
+ dst[1] = FZ_BLEND(g, dst[1], ca);
+ dst += 2;
+ }
+}
+
+static void
path_w4i1o4(byte * restrict argb, byte * restrict src, byte cov, int len, byte * restrict dst)
{
int alpha = FZ_EXPAND(argb[0]);
byte r = argb[1];
byte g = argb[2];
byte b = argb[3];
+
while (len--)
{
int ca;
@@ -218,12 +238,37 @@ text_1o1(byte * restrict src, int srcw, byte * restrict dst, int dstw, int w0, i
}
static void
+text_w2i1o2(byte * restrict ag, byte * restrict src, int srcw, byte * restrict dst, int dstw, int w0, int h)
+{
+ int alpha = FZ_EXPAND(ag[0]);
+ byte g = ag[1];
+
+ srcw -= w0;
+ dstw -= w0<<1;
+ while (h--)
+ {
+ int w = w0;
+ while (w--)
+ {
+ int c = FZ_COMBINE(FZ_EXPAND(src[0]), alpha);
+ dst[0] = FZ_BLEND(255, dst[0], c);
+ dst[1] = FZ_BLEND(g, dst[1], c);
+ src ++;
+ dst += 2;
+ }
+ src += srcw;
+ dst += dstw;
+ }
+}
+
+static void
text_w4i1o4(byte * restrict argb, byte * restrict src, int srcw, byte * restrict dst, int dstw, int w0, int h)
{
int alpha = FZ_EXPAND(argb[0]);
byte r = argb[1];
byte g = argb[2];
byte b = argb[3];
+
srcw -= w0;
dstw -= w0<<2;
while (h--)
@@ -256,7 +301,9 @@ void (*fz_duff_1i1o1)(byte*,int,byte*,int,byte*,int,int,int) = duff_1i1o1;
void (*fz_duff_4i1o4)(byte*,int,byte*,int,byte*,int,int,int) = duff_4i1o4;
void (*fz_path_1o1)(byte*,byte,int,byte*) = path_1o1;
+void (*fz_path_w2i1o2)(byte*,byte*,byte,int,byte*) = path_w2i1o2;
void (*fz_path_w4i1o4)(byte*,byte*,byte,int,byte*) = path_w4i1o4;
void (*fz_text_1o1)(byte*,int,byte*,int,int,int) = text_1o1;
+void (*fz_text_w2i1o2)(byte*,byte*,int,byte*,int,int,int) = text_w2i1o2;
void (*fz_text_w4i1o4)(byte*,byte*,int,byte*,int,int,int) = text_w4i1o4;
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c
index 0b909f85..2698f22d 100644
--- a/fitz/dev_draw.c
+++ b/fitz/dev_draw.c
@@ -277,7 +277,20 @@ drawglyph(unsigned char *argb, fz_pixmap *dst, fz_pixmap *src, int xorig, int yo
h = sy1 - sy0;
if (dst->colorspace)
- fz_text_w4i1o4(argb, sp, src->w, dp, dst->w * 4, w, h);
+ {
+ switch (dst->n)
+ {
+ case 2:
+ fz_text_w2i1o2(argb, sp, src->w, dp, dst->w * 2, w, h);
+ break;
+ case 4:
+ fz_text_w4i1o4(argb, sp, src->w, dp, dst->w * 4, w, h);
+ break;
+ default:
+ assert("Write fz_text_wni1on" != NULL);
+ break;
+ }
+ }
else
fz_text_1o1(sp, src->w, dp, dst->w, w, h);
}
diff --git a/fitz/fitz_draw.h b/fitz/fitz_draw.h
index 077edd0b..abd94a1e 100644
--- a/fitz/fitz_draw.h
+++ b/fitz/fitz_draw.h
@@ -487,14 +487,18 @@ extern void (*fz_duff_1i1o1)(unsigned char*,int,unsigned char*,int,unsigned char
extern void (*fz_duff_4i1o4)(unsigned char*,int,unsigned char*,int,unsigned char*,int,int,int);
extern void (*fz_path_1o1)(unsigned char*,unsigned char,int,unsigned char*);
+extern void (*fz_path_w2i1o2)(unsigned char*,unsigned char*,unsigned char,int,unsigned char*);
extern void (*fz_path_w4i1o4)(unsigned char*,unsigned char*,unsigned char,int,unsigned char*);
extern void (*fz_text_1o1)(unsigned char*,int,unsigned char*,int,int,int);
+extern void (*fz_text_w2i1o2)(unsigned char*,unsigned char*,int,unsigned char*,int,int,int);
extern void (*fz_text_w4i1o4)(unsigned char*,unsigned char*,int,unsigned char*,int,int,int);
extern void (*fz_img_non)(unsigned char*,unsigned char,int,unsigned char*,fz_pixmap*,fz_matrix*);
extern void (*fz_img_1o1)(unsigned char*,unsigned char,int,unsigned char*,fz_pixmap*,int u, int v, int fa, int fb);
extern void (*fz_img_4o4)(unsigned char*,unsigned char,int,unsigned char*,fz_pixmap*,int u, int v, int fa, int fb);
+extern void (*fz_img_2o2)(unsigned char*,unsigned char,int,unsigned char*,fz_pixmap*,int u, int v, int fa, int fb);
+extern void (*fz_img_w2i1o2)(unsigned char*,unsigned char*,unsigned char,int,unsigned char*,fz_pixmap*,int u, int v, int fa, int fb);
extern void (*fz_img_w4i1o4)(unsigned char*,unsigned char*,unsigned char,int,unsigned char*,fz_pixmap*,int u, int v, int fa, int fb);
extern void (*fz_decodetile)(fz_pixmap *pix, int skip, float *decode);