Bug 565120: Do not upload partially when not required. r=jrmuizel

This commit is contained in:
Bas Schouten 2010-06-19 16:32:48 +02:00
parent c454f0272a
commit fdc01fa365

View File

@ -632,6 +632,56 @@ static void _d2d_snapshot_detached(cairo_surface_t *surface)
cairo_surface_destroy(surface);
}
static void
_cairo_d2d_calculate_visible_rect(cairo_d2d_surface_t *d2dsurf, cairo_image_surface_t *srcSurf,
cairo_matrix_t *mat,
int *x, int *y, unsigned int *width, unsigned int *height)
{
/** Leave room for extend_none space, 2 pixels */
UINT32 maxSize = d2dsurf->rt->GetMaximumBitmapSize() - 2;
/* Transform this surface to image surface space */
cairo_matrix_t invMat = *mat;
if (_cairo_matrix_is_invertible(mat)) {
/* If this is not invertible it will be rank zero, and invMat = mat is fine */
cairo_matrix_invert(&invMat);
}
RefPtr<IDXGISurface> surf;
d2dsurf->surface->QueryInterface(&surf);
DXGI_SURFACE_DESC desc;
surf->GetDesc(&desc);
double leftMost = 0;
double rightMost = desc.Width;
double topMost = 0;
double bottomMost = desc.Height;
_cairo_matrix_transform_bounding_box(&invMat, &leftMost, &topMost, &rightMost, &bottomMost, NULL);
leftMost -= 1;
topMost -= 1;
rightMost += 1;
bottomMost += 1;
/* Calculate the offsets into the source image and the width of the part required */
if ((UINT32)srcSurf->width > maxSize) {
*x = (int)MAX(0, floor(leftMost));
*width = (unsigned int)MIN(MAX(0, ceil(rightMost - *x)), srcSurf->width - *x);
} else {
*x = 0;
*width = srcSurf->width;
}
if ((UINT32)srcSurf->height > maxSize) {
*y = (int)MAX(0, floor(topMost));
*height = (unsigned int)MIN(MAX(0, ceil(bottomMost - *y)), srcSurf->height - *y);
} else {
*y = 0;
*height = srcSurf->height;
}
}
/**
* This creates an ID2D1Brush that will fill with the correct pattern.
* This function passes a -strong- reference to the caller, the brush
@ -777,8 +827,8 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
RefPtr<ID2D1Bitmap> sourceBitmap;
bool partial = false;
unsigned int xoffset = 0;
unsigned int yoffset = 0;
int xoffset = 0;
int yoffset = 0;
unsigned int width;
unsigned int height;
unsigned char *data = NULL;
@ -834,37 +884,9 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
if ((UINT32)srcSurf->width > maxSize || (UINT32)srcSurf->height > maxSize) {
/* We cannot fit this image directly into a texture, start doing tricks to draw correctly anyway. */
partial = true;
/* First we check which part of the image is inside the viewable area. */
/* Transform this surface to image surface space */
cairo_matrix_t invMat = mat;
if (_cairo_matrix_is_invertible(&mat)) {
/* If this is not invertible it will be rank zero, and invMat = mat is fine */
cairo_matrix_invert(&invMat);
}
RefPtr<IDXGISurface> surf;
d2dsurf->surface->QueryInterface(&surf);
DXGI_SURFACE_DESC desc;
surf->GetDesc(&desc);
double leftMost = 0;
double rightMost = desc.Width;
double topMost = 0;
double bottomMost = desc.Height;
_cairo_matrix_transform_bounding_box(&invMat, &leftMost, &topMost, &rightMost, &bottomMost, NULL);
leftMost -= 1;
topMost -= 1;
rightMost += 1;
bottomMost += 1;
/* Calculate the offsets into the source image and the width of the part required */
xoffset = (unsigned int)MAX(0, floor(leftMost));
yoffset = (unsigned int)MAX(0, floor(topMost));
width = (unsigned int)MIN(MAX(0, ceil(rightMost - xoffset)), srcSurf->width - xoffset);
height = (unsigned int)MIN(MAX(0, ceil(bottomMost - yoffset)), srcSurf->height - yoffset);
_cairo_d2d_calculate_visible_rect(d2dsurf, srcSurf, &mat, &xoffset, &yoffset, &width, &height);
cairo_matrix_translate(&mat, xoffset, yoffset);
@ -882,6 +904,11 @@ _cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
* this by 45 degrees and scale it to a size of 5x5 pixels and composite it to the destination,
* the composition will require all 10 original columns to do the best possible sampling.
*/
RefPtr<IDXGISurface> surf;
d2dsurf->surface->QueryInterface(&surf);
DXGI_SURFACE_DESC desc;
surf->GetDesc(&desc);
unsigned int minSize = (unsigned int)ceil(sqrt(pow((float)desc.Width, 2) + pow((float)desc.Height, 2)));
unsigned int newWidth = MIN(minSize, MIN(width, maxSize));