diff -urNp CairoOutputDev_orig.cc CairoOutputDev.cc --- CairoOutputDev_orig.cc 2009-11-16 21:58:17.000000000 +0100 +++ CairoOutputDev.cc 2009-12-02 18:53:27.000000000 +0100 @@ -96,6 +96,69 @@ void CairoImage::setImage (cairo_surface this->image = cairo_surface_reference (image); } + + +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 //------------------------------------------------------------------------ @@ -1963,13 +2026,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) { @@ -1982,11 +2072,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(); @@ -2028,6 +2116,13 @@ void CairoOutputDev::drawImage(GfxState } gfree(lookup); + + if (scaledWidth