Commit 6a19d9f2 authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Support drawing to a visible rectangle smaller than the whole bitmap in the DIB engine.

parent 025b5887
......@@ -675,9 +675,11 @@ static DWORD copy_src_bits( dib_info *src, RECT *src_rect )
for (y = 0; y < height; y++)
memcpy( (char *)ptr + y * stride,
(char *)src->bits.ptr + (src_rect->top + y) * src->stride, stride );
(char *)src->bits.ptr + (src->rect.top + src_rect->top + y) * src->stride, stride );
src->stride = stride;
src->height = height;
src->rect.top = 0;
src->rect.bottom = height;
if (src->bits.free) src->bits.free( &src->bits );
src->bits.is_copy = TRUE;
src->bits.ptr = ptr;
......@@ -694,6 +696,10 @@ static DWORD create_tmp_dib( const dib_info *copy, int width, int height, dib_in
ret->width = width;
ret->height = height;
ret->stride = get_dib_stride( width, ret->bit_count );
ret->rect.left = 0;
ret->rect.top = 0;
ret->rect.right = width;
ret->rect.bottom = height;
ret->bits.ptr = HeapAlloc( GetProcessHeap(), 0, ret->height * ret->stride );
ret->bits.is_copy = TRUE;
ret->bits.free = free_heap_bits;
......@@ -839,19 +845,23 @@ DWORD dibdrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
}
info->bmiHeader.biWidth = dib->width;
info->bmiHeader.biHeight = dib->stride > 0 ? -dib->height : dib->height;
info->bmiHeader.biHeight = dib->rect.bottom - dib->rect.top;
info->bmiHeader.biBitCount = dib->bit_count;
info->bmiHeader.biSizeImage = dib->height * abs( dib->stride );
info->bmiHeader.biSizeImage = info->bmiHeader.biHeight * abs( dib->stride );
if (dib->stride > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight;
set_color_info( dib, info );
if (bits)
{
bits->ptr = dib->bits.ptr;
if (dib->stride < 0)
bits->ptr = (char *)bits->ptr + (dib->height - 1) * dib->stride;
bits->ptr = (char *)dib->bits.ptr + (dib->rect.bottom - 1) * dib->stride;
else
bits->ptr = (char *)dib->bits.ptr + dib->rect.top * dib->stride;
bits->is_copy = FALSE;
bits->free = NULL;
src->x += dib->rect.left;
offset_rect( &src->visrect, dib->rect.left, 0 );
}
done:
......
......@@ -73,6 +73,10 @@ static void init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD
dib->bit_count = bi->biBitCount;
dib->width = bi->biWidth;
dib->height = bi->biHeight;
dib->rect.left = 0;
dib->rect.top = 0;
dib->rect.right = bi->biWidth;
dib->rect.bottom = abs( bi->biHeight );
dib->compression = bi->biCompression;
dib->stride = get_dib_stride( dib->width, dib->bit_count );
dib->bits.ptr = bits;
......@@ -267,8 +271,8 @@ int get_clipped_rects( const dib_info *dib, const RECT *rc, HRGN clip, struct cl
rect.left = 0;
rect.top = 0;
rect.right = dib->width;
rect.bottom = dib->height;
rect.right = dib->rect.right - dib->rect.left;
rect.bottom = dib->rect.bottom - dib->rect.top;
if (rc && !intersect_rect( &rect, &rect, rc )) return 0;
if (!clip)
......@@ -313,6 +317,8 @@ void add_clipped_bounds( dibdrv_physdev *dev, const RECT *rect, HRGN clip )
}
else rc = *rect;
if (is_rect_empty( &rc )) return;
offset_rect( &rc, dev->dib.rect.left, dev->dib.rect.top );
add_bounds_rect( dev->bounds, &rc );
}
......
......@@ -27,6 +27,7 @@ typedef struct
{
int bit_count, width, height;
int compression;
RECT rect; /* visible rectangle relative to bitmap origin */
int stride; /* stride in bytes. Will be -ve for bottom-up dibs (see bits). */
struct gdi_image_bits bits; /* bits.ptr points to the top-left corner of the dib. */
......
......@@ -438,11 +438,15 @@ static void draw_glyph( dibdrv_physdev *pdev, const POINT *origin, const GLYPHME
POINT src_origin;
dib_info glyph_dib;
glyph_dib.bit_count = 8;
glyph_dib.width = metrics->gmBlackBoxX;
glyph_dib.height = metrics->gmBlackBoxY;
glyph_dib.stride = get_dib_stride( metrics->gmBlackBoxX, 8 );
glyph_dib.bits = *image;
glyph_dib.bit_count = 8;
glyph_dib.width = metrics->gmBlackBoxX;
glyph_dib.height = metrics->gmBlackBoxY;
glyph_dib.rect.left = 0;
glyph_dib.rect.top = 0;
glyph_dib.rect.right = metrics->gmBlackBoxX;
glyph_dib.rect.bottom = metrics->gmBlackBoxY;
glyph_dib.stride = get_dib_stride( metrics->gmBlackBoxX, 8 );
glyph_dib.bits = *image;
rect.left = origin->x + metrics->gmptGlyphOrigin.x;
rect.top = origin->y - metrics->gmptGlyphOrigin.y;
......@@ -587,11 +591,15 @@ BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits
POINT src_origin;
dib_info glyph_dib;
glyph_dib.bit_count = 8;
glyph_dib.width = metrics.gmBlackBoxX;
glyph_dib.height = metrics.gmBlackBoxY;
glyph_dib.stride = get_dib_stride( metrics.gmBlackBoxX, 8 );
glyph_dib.bits = image;
glyph_dib.bit_count = 8;
glyph_dib.width = metrics.gmBlackBoxX;
glyph_dib.height = metrics.gmBlackBoxY;
glyph_dib.rect.left = 0;
glyph_dib.rect.top = 0;
glyph_dib.rect.right = metrics.gmBlackBoxX;
glyph_dib.rect.bottom = metrics.gmBlackBoxY;
glyph_dib.stride = get_dib_stride( metrics.gmBlackBoxX, 8 );
glyph_dib.bits = image;
rect.left = x + metrics.gmptGlyphOrigin.x;
rect.top = y - metrics.gmptGlyphOrigin.y;
......@@ -783,13 +791,15 @@ static inline void do_next_row( dib_info *dib, HRGN clip, const RECT *row, int o
static void fill_row( dib_info *dib, HRGN clip, RECT *row, DWORD pixel, UINT type, HRGN rgn )
{
while (row->left > 0 && is_interior( dib, clip, row->left - 1, row->top, pixel, type)) row->left--;
while (row->right < dib->width && is_interior( dib, clip, row->right, row->top, pixel, type)) row->right++;
while (row->right < dib->rect.right - dib->rect.left &&
is_interior( dib, clip, row->right, row->top, pixel, type))
row->right++;
add_rect_to_region( rgn, row );
if (row->top > 0) do_next_row( dib, clip, row, -1, pixel, type, rgn );
if (row->top < dib->height - 1) do_next_row( dib, clip, row, 1, pixel, type, rgn );
return;
if (row->top < dib->rect.bottom - dib->rect.top - 1)
do_next_row( dib, clip, row, 1, pixel, type, rgn );
}
/***********************************************************************
......@@ -850,8 +860,8 @@ COLORREF dibdrv_GetPixel( PHYSDEV dev, INT x, INT y )
pt.y = y;
LPtoDP( dev->hdc, &pt, 1 );
if (pt.x < 0 || pt.x >= pdev->dib.width ||
pt.y < 0 || pt.y >= pdev->dib.height)
if (pt.x < 0 || pt.x >= pdev->dib.rect.right - pdev->dib.rect.left ||
pt.y < 0 || pt.y >= pdev->dib.rect.bottom - pdev->dib.rect.top)
return CLR_INVALID;
pixel = pdev->dib.funcs->get_pixel( &pdev->dib, pt.x, pt.y );
......
......@@ -1805,6 +1805,10 @@ static BOOL create_hatch_brush_bits(dibdrv_physdev *pdev, dib_brush *brush, BOOL
brush->dib.width = 8;
brush->dib.height = 8;
brush->dib.stride = get_dib_stride( brush->dib.width, brush->dib.bit_count );
brush->dib.rect.left = 0;
brush->dib.rect.top = 0;
brush->dib.rect.right = 8;
brush->dib.rect.bottom = 8;
size = brush->dib.height * brush->dib.stride;
......@@ -1824,6 +1828,10 @@ static BOOL create_hatch_brush_bits(dibdrv_physdev *pdev, dib_brush *brush, BOOL
hatch.bits.ptr = (void *) hatches[brush->hatch];
hatch.bits.free = hatch.bits.param = NULL;
hatch.bits.is_copy = FALSE;
hatch.rect.left = 0;
hatch.rect.top = 0;
hatch.rect.right = 8;
hatch.rect.bottom = 8;
get_color_masks( pdev, brush->rop, brush->colorref, GetBkMode(pdev->dev.hdc),
&fg_mask, &bg_mask );
......@@ -1865,7 +1873,6 @@ static BOOL select_pattern_brush( dibdrv_physdev *pdev, dib_brush *brush, BOOL *
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
BITMAPINFO *info = (BITMAPINFO *)buffer;
RGBQUAD color_table[2];
RECT rect;
dib_info pattern;
if (!brush->pattern.info)
......@@ -1921,6 +1928,7 @@ static BOOL select_pattern_brush( dibdrv_physdev *pdev, dib_brush *brush, BOOL *
brush->dib.height = pattern.height;
brush->dib.width = pattern.width;
brush->dib.stride = get_dib_stride( brush->dib.width, brush->dib.bit_count );
brush->dib.rect = pattern.rect;
if (matching_pattern_format( &brush->dib, &pattern ))
{
......@@ -1933,12 +1941,7 @@ static BOOL select_pattern_brush( dibdrv_physdev *pdev, dib_brush *brush, BOOL *
brush->dib.bits.ptr = HeapAlloc( GetProcessHeap(), 0, brush->dib.height * brush->dib.stride );
brush->dib.bits.is_copy = TRUE;
brush->dib.bits.free = free_heap_bits;
rect.left = rect.top = 0;
rect.right = pattern.width;
rect.bottom = pattern.height;
brush->dib.funcs->convert_to(&brush->dib, &pattern, &rect);
brush->dib.funcs->convert_to(&brush->dib, &pattern, &pattern.rect);
}
return TRUE;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment