Index: poppler/CairoOutputDev.cc =================================================================== RCS file: /cvs/poppler/poppler/poppler/CairoOutputDev.cc,v retrieving revision 1.45 diff -u -r1.45 CairoOutputDev.cc --- poppler/CairoOutputDev.cc 7 Nov 2006 23:53:31 -0000 1.45 +++ poppler/CairoOutputDev.cc 10 Dec 2006 02:22:36 -0000 @@ -485,6 +485,10 @@ } +static inline int splashRound(SplashCoord x) { + return (int)floor(x + 0.5); +} + void CairoOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, @@ -511,13 +515,45 @@ cairo_restore (cairo); return; } + /*XXX BUGS: cannadoc 013 - the arrow should be filled in but it is not. */ + cairo_get_matrix(cairo, &matrix); + printf("[%f %f], [%f %f], %f %f\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.x0, matrix.y0); + //{ + double xScale = matrix.xx; + double yScale = matrix.yy; + int tx, tx2, ty, ty2; + int scaledHeight = height; + int scaledWidth = width; + if (xScale >= 0) { + tx = splashRound(matrix.x0 - 0.01); + tx2 = splashRound(matrix.x0 + xScale + 0.01) - 1; + } else { + tx = splashRound(matrix.x0 + 0.01) - 1; + tx2 = splashRound(matrix.x0 + xScale - 0.01); + } + scaledWidth = abs(tx2 - tx) + 1; + scaledWidth = splashRound(fabs(xScale)); + if (scaledWidth == 0) { + // technically, this should draw nothing, but it generally seems + // better to draw a one-pixel-wide stripe rather than throwing it + // away + scaledWidth = 1; + } + if (yScale >= 0) { + ty = splashRound(matrix.y0 - 0.01); + ty2 = splashRound(matrix.y0 + yScale + 0.01) - 1; + } else { + ty = splashRound(matrix.y0 + 0.01) - 1; + ty2 = splashRound(matrix.y0 + yScale - 0.01); + } + scaledHeight = abs(ty2 - ty) + 1; + scaledHeight = splashRound(fabs(yScale)); - row_stride = (width + 3) & ~3; - buffer = (unsigned char *) malloc (height * row_stride); - if (buffer == NULL) { - error(-1, "Unable to allocate memory for image."); - return; - } + printf("xscale: %g, yscale: %g\n", xScale, yScale); + printf("width: %d, height: %d\n", width, height); + printf("scaledWidth: %d, scaledHeight: %d\n", scaledWidth, scaledHeight); + printf("ty: %d, ty2: %d\n", ty, ty2); + //} /* TODO: Do we want to cache these? */ imgStr = new ImageStream(str, width, 1, 1); @@ -525,6 +561,14 @@ invert_bit = invert ? 1 : 0; + row_stride = (scaledWidth + 3) & ~3; + buffer = (unsigned char *) malloc (scaledHeight * row_stride); + if (buffer == NULL) { + error(-1, "Unable to allocate memory for image."); + return; + } + +#if 0 for (y = 0; y < height; y++) { pix = imgStr->getLine(); dest = buffer + y * row_stride; @@ -536,9 +580,74 @@ *dest++ = 255; } } +#else + int yp = height / scaledHeight; + int yq = height % scaledHeight; + int xp = width / scaledWidth; + int xq = width % scaledWidth; +// int p_position = 0; + int yt = 0; + unsigned char *pixBuf = (unsigned char *)malloc((yp + 1)*width); + int lastYStep = 1; + for (int y = 0; y < scaledHeight; y++) { + // y scale Bresenham + int yStep = yp; + yt += yq; + + if (yt >= scaledHeight) { + yt -= scaledHeight; + ++yStep; + } + + // read row (s) from image + { + int n = (yp > 0) ? yStep : lastYStep; + if (n > 0) { + unsigned char *p = pixBuf; + for (int i=0; igetLine(); + for (int j=0; j 0 ? yStep : 1; + for (int x = 0; x < scaledWidth; ++x) { + int xStep = xp; + xt += xq; + if (xt >= scaledWidth) { + xt -= scaledWidth; + ++xStep; + } + int m = xStep > 0 ? xStep : 1; + int pixAcc0 = 0; + for (int i = 0; i < n; ++i) { + for (int j = 0; j< m; ++j) { + pixAcc0 += pixBuf[xSrc + i*width + j]; + } + } + buffer[y * row_stride + x] = pixAcc0 / (n*m); + xSrc += xStep; + x1 += 1; + } + } + free(pixBuf); +#endif image = cairo_image_surface_create_for_data (buffer, CAIRO_FORMAT_A8, - width, height, row_stride); + scaledWidth, scaledHeight, row_stride); if (image == NULL) { delete imgStr; return; @@ -549,18 +658,27 @@ return; } - cairo_matrix_init_translate (&matrix, 0, height); - cairo_matrix_scale (&matrix, width, -height); + //cairo_matrix_init_translate (&matrix, 0, -scaledHeight); +// cairo_matrix_scale (&matrix, width, -height); - cairo_pattern_set_matrix (pattern, &matrix); + //cairo_pattern_set_matrix (pattern, &matrix); /* we should actually be using CAIRO_FILTER_NEAREST here. However, * cairo doesn't yet do minifaction filtering causing scaled down * images with CAIRO_FILTER_NEAREST to look really bad */ cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST); - - cairo_mask (cairo, pattern); - + { + cairo_get_matrix(cairo, &matrix); + cairo_save (cairo); + cairo_scale(cairo, 1.0/matrix.xx, 1.0/matrix.yy); + cairo_translate (cairo, tx - matrix.x0, splashRound(fabs(matrix.y0 + yScale)) - matrix.y0); + if (yScale > 0) + cairo_scale(cairo, 1, -1); + cairo_mask (cairo, pattern); + cairo_get_matrix(cairo, &matrix); + printf("mask at: [%f %f], [%f %f], %f %f\n\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy, matrix.x0, matrix.y0); + cairo_restore(cairo); + } cairo_pattern_destroy (pattern); cairo_surface_destroy (image); free (buffer);