diff -up poppler-0.12.3/poppler/CairoOutputDev.cc.rex poppler-0.12.3/poppler/CairoOutputDev.cc --- poppler-0.12.3/poppler/CairoOutputDev.cc.rex 2009-12-24 04:41:22.000000000 -0600 +++ poppler-0.12.3/poppler/CairoOutputDev.cc 2010-01-19 12:14:33.210386122 -0600 @@ -97,6 +97,69 @@ void CairoImage::setImage (cairo_surface this->image = cairo_surface_reference (image); } +// basic 2D box filter +void PrescaleARGB(unsigned int * source,int width,int height,int stride,unsigned int * dest,int scaledWidth,int scaledHeight,int scaledStride) +{ + stride/=4; + scaledStride/=4; + // sanity check + if (scaledHeight>height || scaledWidth>width || scaledHeight<=0 || scaledWidth<=0 || stride>8)&0xFF; + sum3+=(pLine[sx]>>16)&0xFF; + sum4+=pLine[sx]>>24; + } // sum x + pLine+=stride; + } // sum y + pLine=pt+dx; + count=dx*dy; + dest[z++]=sum1/count+(sum2/count<<8)+(sum3/count<<16)+(sum4/count<<24); + } // row + oy+=dy; + } + + delete [] pixelwidth; +} + + + //------------------------------------------------------------------------ // CairoOutputDev //------------------------------------------------------------------------ @@ -1975,13 +2038,40 @@ void CairoOutputDev::drawImage(GfxState ((GfxICCBasedColorSpace*)colorMap->getColorSpace())->getAlt()->getMode() == csDeviceRGB); #endif + int scaledWidth,scaledHeight,scaledStride; + unsigned char * scaledBuffer; + + cairo_get_matrix(cairo, &matrix); + scaledWidth=fabs(matrix.xx+matrix.yx)+0.5; + scaledHeight=fabs(matrix.xy+matrix.yy)+0.5; + + if (printing || scaledWidth>=width || scaledHeight>=height) + { // no prescaling => render directly to cairo_image + scaledWidth=width; + scaledHeight=height; + } + else + { // first render to ARGB buffer then downsample to cairo_image + stride = width*4; + buffer = new unsigned char [stride*height]; + } + image = cairo_image_surface_create (maskColors ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, - width, height); + scaledWidth, scaledHeight); if (cairo_surface_status (image)) goto cleanup; + + scaledBuffer = cairo_image_surface_get_data (image); + scaledStride = cairo_image_surface_get_stride (image); + if (scaledWidth>=width || scaledHeight>=height) + { // no prescaling => render directly to cairo_image + stride = scaledStride; + buffer = scaledBuffer; + } + // special case for one-channel (monochrome/gray/separation) images: // build a lookup table here if (colorMap->getNumPixelComps() == 1) { @@ -1994,11 +2084,9 @@ void CairoOutputDev::drawImage(GfxState pix = (Guchar)i; colorMap->getRGB(&pix, &lookup[i]); - } - } + } + } - buffer = cairo_image_surface_get_data (image); - stride = cairo_image_surface_get_stride (image); for (int y = 0; y < height; y++) { uint32_t *dest = (uint32_t *) (buffer + y * stride); Guchar *pix = imgStr->getLine(); @@ -2040,6 +2128,12 @@ void CairoOutputDev::drawImage(GfxState } gfree(lookup); + if (scaledWidth