gdi32: Use the DIB engine and PutImage for the null driver triangular gradient implementation.
This commit is contained in:
parent
8e8cdc78e6
commit
360d4bc548
|
@ -21,7 +21,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <limits.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#ifdef HAVE_FLOAT_H
|
#ifdef HAVE_FLOAT_H
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
@ -407,152 +407,85 @@ BOOL nulldrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG nvert,
|
||||||
struct bitblt_coords src, dst;
|
struct bitblt_coords src, dst;
|
||||||
struct gdi_image_bits bits;
|
struct gdi_image_bits bits;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
POINT *pts;
|
||||||
|
RECT clip;
|
||||||
|
BOOL ret = TRUE;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
|
HRGN rgn;
|
||||||
|
|
||||||
switch(mode)
|
if (!(pts = HeapAlloc( GetProcessHeap(), 0, nvert * sizeof(*pts) ))) return FALSE;
|
||||||
|
for (i = 0; i < nvert; i++)
|
||||||
{
|
{
|
||||||
case GRADIENT_FILL_RECT_H:
|
pts[i].x = vert_array[i].x;
|
||||||
case GRADIENT_FILL_RECT_V:
|
pts[i].y = vert_array[i].y;
|
||||||
{
|
|
||||||
const GRADIENT_RECT *rect = grad_array;
|
|
||||||
TRIVERTEX v[2];
|
|
||||||
|
|
||||||
for (i = 0; i < ngrad; i++, rect++)
|
|
||||||
{
|
|
||||||
v[0] = vert_array[rect->UpperLeft];
|
|
||||||
v[1] = vert_array[rect->LowerRight];
|
|
||||||
|
|
||||||
dst.log_x = v[0].x;
|
|
||||||
dst.log_y = v[0].y;
|
|
||||||
dst.log_width = v[1].x - v[0].x;
|
|
||||||
dst.log_height = v[1].y - v[0].y;
|
|
||||||
dst.layout = dc->layout;
|
|
||||||
if (!get_vis_rectangles( dc, &dst, NULL, NULL )) continue;
|
|
||||||
|
|
||||||
if (dst.width < 0)
|
|
||||||
{
|
|
||||||
if (mode == GRADIENT_FILL_RECT_H) /* swap the colors */
|
|
||||||
{
|
|
||||||
v[0] = vert_array[rect->LowerRight];
|
|
||||||
v[1] = vert_array[rect->UpperLeft];
|
|
||||||
}
|
|
||||||
dst.x += dst.width + 1;
|
|
||||||
dst.width = -dst.width;
|
|
||||||
}
|
|
||||||
if (dst.height < 0)
|
|
||||||
{
|
|
||||||
if (mode == GRADIENT_FILL_RECT_V) /* swap the colors */
|
|
||||||
{
|
|
||||||
v[0] = vert_array[rect->LowerRight];
|
|
||||||
v[1] = vert_array[rect->UpperLeft];
|
|
||||||
}
|
|
||||||
dst.y += dst.height + 1;
|
|
||||||
dst.height = -dst.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* query the bitmap format */
|
|
||||||
info->bmiHeader.biSize = sizeof(info->bmiHeader);
|
|
||||||
info->bmiHeader.biPlanes = 1;
|
|
||||||
info->bmiHeader.biBitCount = 0;
|
|
||||||
info->bmiHeader.biCompression = BI_RGB;
|
|
||||||
info->bmiHeader.biXPelsPerMeter = 0;
|
|
||||||
info->bmiHeader.biYPelsPerMeter = 0;
|
|
||||||
info->bmiHeader.biClrUsed = 0;
|
|
||||||
info->bmiHeader.biClrImportant = 0;
|
|
||||||
info->bmiHeader.biWidth = dst.visrect.right - dst.visrect.left;
|
|
||||||
info->bmiHeader.biHeight = dst.visrect.bottom - dst.visrect.top;
|
|
||||||
info->bmiHeader.biSizeImage = 0;
|
|
||||||
dev = GET_DC_PHYSDEV( dc, pPutImage );
|
|
||||||
err = dev->funcs->pPutImage( dev, 0, 0, info, NULL, NULL, NULL, 0 );
|
|
||||||
if (!err || err == ERROR_BAD_FORMAT)
|
|
||||||
{
|
|
||||||
if (!(bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ))))
|
|
||||||
return FALSE;
|
|
||||||
bits.is_copy = TRUE;
|
|
||||||
bits.free = free_heap_bits;
|
|
||||||
|
|
||||||
/* make src relative to the bitmap */
|
|
||||||
src = dst;
|
|
||||||
src.x -= src.visrect.left;
|
|
||||||
src.y -= src.visrect.top;
|
|
||||||
offset_rect( &src.visrect, -src.visrect.left, -src.visrect.top );
|
|
||||||
v[0].x = src.x;
|
|
||||||
v[0].y = src.y;
|
|
||||||
v[1].x = src.x + src.width;
|
|
||||||
v[1].y = src.y + src.height;
|
|
||||||
err = gradient_bitmapinfo( info, bits.ptr, v, mode );
|
|
||||||
|
|
||||||
if (!err) err = dev->funcs->pPutImage( dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
|
|
||||||
if (bits.free) bits.free( &bits );
|
|
||||||
}
|
|
||||||
if (err) return FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case GRADIENT_FILL_TRIANGLE:
|
LPtoDP( dev->hdc, pts, nvert );
|
||||||
for (i = 0; i < ngrad; i++)
|
|
||||||
{
|
|
||||||
GRADIENT_TRIANGLE *tri = ((GRADIENT_TRIANGLE *)grad_array) + i;
|
|
||||||
TRIVERTEX *v1 = vert_array + tri->Vertex1;
|
|
||||||
TRIVERTEX *v2 = vert_array + tri->Vertex2;
|
|
||||||
TRIVERTEX *v3 = vert_array + tri->Vertex3;
|
|
||||||
int y, dy;
|
|
||||||
|
|
||||||
if (v1->y > v2->y)
|
/* compute bounding rect of all the rectangles/triangles */
|
||||||
{ TRIVERTEX *t = v1; v1 = v2; v2 = t; }
|
dst.visrect.left = dst.visrect.top = INT_MAX;
|
||||||
if (v2->y > v3->y)
|
dst.visrect.right = dst.visrect.bottom = INT_MIN;
|
||||||
{
|
for (i = 0; i < ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2); i++)
|
||||||
TRIVERTEX *t = v2; v2 = v3; v3 = t;
|
{
|
||||||
if (v1->y > v2->y)
|
ULONG v = ((ULONG *)grad_array)[i];
|
||||||
{ t = v1; v1 = v2; v2 = t; }
|
dst.visrect.left = min( dst.visrect.left, pts[v].x );
|
||||||
}
|
dst.visrect.top = min( dst.visrect.top, pts[v].y );
|
||||||
/* v1->y <= v2->y <= v3->y */
|
dst.visrect.right = max( dst.visrect.right, pts[v].x );
|
||||||
|
dst.visrect.bottom = max( dst.visrect.bottom, pts[v].y );
|
||||||
dy = v3->y - v1->y;
|
|
||||||
for (y = 0; y < dy; y++)
|
|
||||||
{
|
|
||||||
/* v1->y <= y < v3->y */
|
|
||||||
TRIVERTEX *v = y < (v2->y - v1->y) ? v1 : v3;
|
|
||||||
/* (v->y <= y < v2->y) || (v2->y <= y < v->y) */
|
|
||||||
int dy2 = v2->y - v->y;
|
|
||||||
int y2 = y + v1->y - v->y;
|
|
||||||
|
|
||||||
int x1 = (v3->x * y + v1->x * (dy - y )) / dy;
|
|
||||||
int x2 = (v2->x * y2 + v-> x * (dy2 - y2)) / dy2;
|
|
||||||
int r1 = (v3->Red * y + v1->Red * (dy - y )) / dy;
|
|
||||||
int r2 = (v2->Red * y2 + v-> Red * (dy2 - y2)) / dy2;
|
|
||||||
int g1 = (v3->Green * y + v1->Green * (dy - y )) / dy;
|
|
||||||
int g2 = (v2->Green * y2 + v-> Green * (dy2 - y2)) / dy2;
|
|
||||||
int b1 = (v3->Blue * y + v1->Blue * (dy - y )) / dy;
|
|
||||||
int b2 = (v2->Blue * y2 + v-> Blue * (dy2 - y2)) / dy2;
|
|
||||||
|
|
||||||
int x;
|
|
||||||
if (x1 < x2)
|
|
||||||
{
|
|
||||||
int dx = x2 - x1;
|
|
||||||
for (x = 0; x < dx; x++)
|
|
||||||
SetPixel (dev->hdc, x + x1, y + v1->y, RGB(
|
|
||||||
(r1 * (dx - x) + r2 * x) / dx >> 8,
|
|
||||||
(g1 * (dx - x) + g2 * x) / dx >> 8,
|
|
||||||
(b1 * (dx - x) + b2 * x) / dx >> 8));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int dx = x1 - x2;
|
|
||||||
for (x = 0; x < dx; x++)
|
|
||||||
SetPixel (dev->hdc, x + x2, y + v1->y, RGB(
|
|
||||||
(r2 * (dx - x) + r1 * x) / dx >> 8,
|
|
||||||
(g2 * (dx - x) + g1 * x) / dx >> 8,
|
|
||||||
(b2 * (dx - x) + b1 * x) / dx >> 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
dst.x = dst.visrect.left;
|
||||||
|
dst.y = dst.visrect.top;
|
||||||
|
dst.width = dst.visrect.right - dst.visrect.left;
|
||||||
|
dst.height = dst.visrect.bottom - dst.visrect.top;
|
||||||
|
|
||||||
|
if (get_clip_box( dc, &clip )) intersect_rect( &dst.visrect, &dst.visrect, &clip );
|
||||||
|
if (is_rect_empty( &dst.visrect )) goto done;
|
||||||
|
|
||||||
|
/* query the bitmap format */
|
||||||
|
info->bmiHeader.biSize = sizeof(info->bmiHeader);
|
||||||
|
info->bmiHeader.biPlanes = 1;
|
||||||
|
info->bmiHeader.biBitCount = 0;
|
||||||
|
info->bmiHeader.biCompression = BI_RGB;
|
||||||
|
info->bmiHeader.biXPelsPerMeter = 0;
|
||||||
|
info->bmiHeader.biYPelsPerMeter = 0;
|
||||||
|
info->bmiHeader.biClrUsed = 0;
|
||||||
|
info->bmiHeader.biClrImportant = 0;
|
||||||
|
info->bmiHeader.biWidth = dst.visrect.right - dst.visrect.left;
|
||||||
|
info->bmiHeader.biHeight = dst.visrect.bottom - dst.visrect.top;
|
||||||
|
info->bmiHeader.biSizeImage = 0;
|
||||||
|
dev = GET_DC_PHYSDEV( dc, pPutImage );
|
||||||
|
err = dev->funcs->pPutImage( dev, 0, 0, info, NULL, NULL, NULL, 0 );
|
||||||
|
if ((err && err != ERROR_BAD_FORMAT) ||
|
||||||
|
!(bits.ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, get_dib_image_size( info ))))
|
||||||
|
{
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
bits.is_copy = TRUE;
|
||||||
|
bits.free = free_heap_bits;
|
||||||
|
|
||||||
|
/* make src and points relative to the bitmap */
|
||||||
|
src = dst;
|
||||||
|
src.x -= dst.visrect.left;
|
||||||
|
src.y -= dst.visrect.top;
|
||||||
|
offset_rect( &src.visrect, -dst.visrect.left, -dst.visrect.top );
|
||||||
|
for (i = 0; i < nvert; i++)
|
||||||
|
{
|
||||||
|
pts[i].x -= dst.visrect.left;
|
||||||
|
pts[i].y -= dst.visrect.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
rgn = CreateRectRgn( 0, 0, 0, 0 );
|
||||||
|
gradient_bitmapinfo( info, bits.ptr, vert_array, nvert, grad_array, ngrad, mode, pts, rgn );
|
||||||
|
OffsetRgn( rgn, dst.visrect.left, dst.visrect.top );
|
||||||
|
if (dev->funcs->pPutImage( dev, 0, rgn, info, &bits, &src, &dst, SRCCOPY )) ret = FALSE;
|
||||||
|
|
||||||
|
if (bits.free) bits.free( &bits );
|
||||||
|
DeleteObject( rgn );
|
||||||
|
|
||||||
|
done:
|
||||||
|
HeapFree( GetProcessHeap(), 0, pts );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -1334,13 +1334,67 @@ DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitbl
|
||||||
return blend_rect( &dst_dib, &dst->visrect, &src_dib, &src->visrect, NULL, blend );
|
return blend_rect( &dst_dib, &dst->visrect, &src_dib, &src->visrect, NULL, blend );
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD gradient_bitmapinfo( const BITMAPINFO *info, void *bits, TRIVERTEX *v, int mode )
|
DWORD gradient_bitmapinfo( const BITMAPINFO *info, void *bits, TRIVERTEX *vert_array, ULONG nvert,
|
||||||
|
void *grad_array, ULONG ngrad, ULONG mode, const POINT *dev_pts, HRGN rgn )
|
||||||
{
|
{
|
||||||
dib_info dib;
|
dib_info dib;
|
||||||
|
const GRADIENT_TRIANGLE *tri = grad_array;
|
||||||
|
const GRADIENT_RECT *rect = grad_array;
|
||||||
|
unsigned int i;
|
||||||
|
int y;
|
||||||
|
TRIVERTEX vert[3];
|
||||||
|
DWORD ret = ERROR_SUCCESS;
|
||||||
|
HRGN tmp_rgn = 0;
|
||||||
|
|
||||||
if (!init_dib_info_from_bitmapinfo( &dib, info, bits, 0 )) return ERROR_BAD_FORMAT;
|
if (!init_dib_info_from_bitmapinfo( &dib, info, bits, 0 )) return ERROR_BAD_FORMAT;
|
||||||
if (!gradient_rect( &dib, v, mode, 0 )) return ERROR_INVALID_PARAMETER;
|
|
||||||
return ERROR_SUCCESS;
|
switch (mode)
|
||||||
|
{
|
||||||
|
case GRADIENT_FILL_RECT_H:
|
||||||
|
for (i = 0; i < ngrad; i++, rect++)
|
||||||
|
{
|
||||||
|
get_gradient_hrect_vertices( rect, vert_array, dev_pts, vert );
|
||||||
|
gradient_rect( &dib, vert, mode, 0 );
|
||||||
|
if (!tmp_rgn) tmp_rgn = CreateRectRgn( vert[0].x, vert[0].y, vert[1].x, vert[1].y );
|
||||||
|
else SetRectRgn( tmp_rgn, vert[0].x, vert[0].y, vert[1].x, vert[1].y );
|
||||||
|
CombineRgn( rgn, rgn, tmp_rgn, RGN_OR );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GRADIENT_FILL_RECT_V:
|
||||||
|
for (i = 0; i < ngrad; i++, rect++)
|
||||||
|
{
|
||||||
|
get_gradient_vrect_vertices( rect, vert_array, dev_pts, vert );
|
||||||
|
gradient_rect( &dib, vert, mode, 0 );
|
||||||
|
if (!tmp_rgn) tmp_rgn = CreateRectRgn( vert[0].x, vert[0].y, vert[1].x, vert[1].y );
|
||||||
|
else SetRectRgn( tmp_rgn, vert[0].x, vert[0].y, vert[1].x, vert[1].y );
|
||||||
|
CombineRgn( rgn, rgn, tmp_rgn, RGN_OR );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GRADIENT_FILL_TRIANGLE:
|
||||||
|
for (i = 0; i < ngrad; i++, tri++)
|
||||||
|
{
|
||||||
|
get_gradient_triangle_vertices( tri, vert_array, dev_pts, vert );
|
||||||
|
if (gradient_rect( &dib, vert, mode, 0 ))
|
||||||
|
{
|
||||||
|
if (!tmp_rgn) tmp_rgn = CreateRectRgn( 0, 0, 0, 0 );
|
||||||
|
for (y = vert[0].y; y < vert[2].y; y++)
|
||||||
|
{
|
||||||
|
int x1, x2 = edge_coord( y, vert[0].x, vert[0].y, vert[2].x, vert[2].y );
|
||||||
|
if (y < vert[1].y) x1 = edge_coord( y, vert[0].x, vert[0].y, vert[1].x, vert[1].y );
|
||||||
|
else x1 = edge_coord( y, vert[1].x, vert[1].y, vert[2].x, vert[2].y );
|
||||||
|
|
||||||
|
SetRectRgn( tmp_rgn, min(x1,x2), y, max(x1,x2), y + 1 );
|
||||||
|
CombineRgn( rgn, rgn, tmp_rgn, RGN_OR );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else ret = ERROR_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DeleteObject( tmp_rgn );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -246,7 +246,8 @@ extern DWORD stretch_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, str
|
||||||
extern DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitblt_coords *src,
|
extern DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitblt_coords *src,
|
||||||
const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst,
|
const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst,
|
||||||
BLENDFUNCTION blend ) DECLSPEC_HIDDEN;
|
BLENDFUNCTION blend ) DECLSPEC_HIDDEN;
|
||||||
extern DWORD gradient_bitmapinfo( const BITMAPINFO *info, void *bits, TRIVERTEX *v, int mode ) DECLSPEC_HIDDEN;
|
extern DWORD gradient_bitmapinfo( const BITMAPINFO *info, void *bits, TRIVERTEX *vert_array, ULONG nvert,
|
||||||
|
void *grad_array, ULONG ngrad, ULONG mode, const POINT *dev_pts, HRGN rgn ) DECLSPEC_HIDDEN;
|
||||||
extern BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits *bits,
|
extern BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits *bits,
|
||||||
struct bitblt_coords *src, INT x, INT y, UINT flags,
|
struct bitblt_coords *src, INT x, INT y, UINT flags,
|
||||||
UINT aa_flags, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
|
UINT aa_flags, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue