mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 11:43:31 +00:00
gdi32: Add support for anti-aliasing in the null driver text output fallback.
This commit is contained in:
parent
1b63d5a610
commit
670f25cc8f
5 changed files with 236 additions and 19 deletions
|
@ -231,6 +231,7 @@ extern void free_dib_info(dib_info *dib) DECLSPEC_HIDDEN;
|
|||
extern void free_pattern_brush(dibdrv_physdev *pdev) DECLSPEC_HIDDEN;
|
||||
extern void copy_dib_color_info(dib_info *dst, const dib_info *src) DECLSPEC_HIDDEN;
|
||||
extern BOOL convert_dib(dib_info *dst, const dib_info *src) DECLSPEC_HIDDEN;
|
||||
extern COLORREF make_rgb_colorref( HDC hdc, dib_info *dib, COLORREF color, BOOL *got_pixel, DWORD *pixel ) DECLSPEC_HIDDEN;
|
||||
extern DWORD get_pixel_color(dibdrv_physdev *pdev, COLORREF color, BOOL mono_fixup) DECLSPEC_HIDDEN;
|
||||
extern BOOL brush_rects( dibdrv_physdev *pdev, int num, const RECT *rects ) DECLSPEC_HIDDEN;
|
||||
extern void solid_rects( dib_info *dib, int num, const RECT *rects, const rop_mask *color, HRGN region ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "gdi_private.h"
|
||||
#include "dibdrv.h"
|
||||
|
||||
|
@ -90,19 +91,24 @@ static inline void get_range( BYTE aa, DWORD text_comp, BYTE *min_comp, BYTE *ma
|
|||
*max_comp = ramp[16 - aa] + ((0xff - ramp[16 - aa]) * text_comp) / 0xff;
|
||||
}
|
||||
|
||||
void update_aa_ranges( dibdrv_physdev *pdev )
|
||||
static inline void get_aa_ranges( COLORREF col, struct intensity_range intensities[17] )
|
||||
{
|
||||
int i;
|
||||
COLORREF text = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pdev->text_color );
|
||||
|
||||
for (i = 0; i < 17; i++)
|
||||
{
|
||||
get_range( i, GetRValue(text), &pdev->glyph_intensities[i].r_min, &pdev->glyph_intensities[i].r_max );
|
||||
get_range( i, GetGValue(text), &pdev->glyph_intensities[i].g_min, &pdev->glyph_intensities[i].g_max );
|
||||
get_range( i, GetBValue(text), &pdev->glyph_intensities[i].b_min, &pdev->glyph_intensities[i].b_max );
|
||||
get_range( i, GetRValue(col), &intensities[i].r_min, &intensities[i].r_max );
|
||||
get_range( i, GetGValue(col), &intensities[i].g_min, &intensities[i].g_max );
|
||||
get_range( i, GetBValue(col), &intensities[i].b_min, &intensities[i].b_max );
|
||||
}
|
||||
}
|
||||
|
||||
void update_aa_ranges( dibdrv_physdev *pdev )
|
||||
{
|
||||
COLORREF text = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pdev->text_color );
|
||||
get_aa_ranges( text, pdev->glyph_intensities );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* get_text_bkgnd_masks
|
||||
*
|
||||
|
@ -168,7 +174,7 @@ static const int padding[4] = {0, 3, 2, 1};
|
|||
* For non-antialiased bitmaps convert them to the 17-level format
|
||||
* using only values 0 or 16.
|
||||
*/
|
||||
static DWORD get_glyph_bitmap( dibdrv_physdev *pdev, UINT index, UINT aa_flags, GLYPHMETRICS *metrics,
|
||||
static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, GLYPHMETRICS *metrics,
|
||||
struct gdi_image_bits *image )
|
||||
{
|
||||
UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
|
||||
|
@ -188,7 +194,7 @@ static DWORD get_glyph_bitmap( dibdrv_physdev *pdev, UINT index, UINT aa_flags,
|
|||
|
||||
for (i = 0; i < sizeof(indices) / sizeof(indices[0]); index = indices[++i])
|
||||
{
|
||||
ret = GetGlyphOutlineW( pdev->dev.hdc, index, ggo_flags, metrics, 0, NULL, &identity );
|
||||
ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
|
||||
if (ret != GDI_ERROR) break;
|
||||
}
|
||||
|
||||
|
@ -203,7 +209,7 @@ static DWORD get_glyph_bitmap( dibdrv_physdev *pdev, UINT index, UINT aa_flags,
|
|||
buf = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
if (!buf) return ERROR_OUTOFMEMORY;
|
||||
|
||||
ret = GetGlyphOutlineW( pdev->dev.hdc, index, ggo_flags, metrics, size, buf, &identity );
|
||||
ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, buf, &identity );
|
||||
if (ret == GDI_ERROR)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, buf );
|
||||
|
@ -233,6 +239,95 @@ static DWORD get_glyph_bitmap( dibdrv_physdev *pdev, UINT index, UINT aa_flags,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits *bits,
|
||||
struct bitblt_coords *src, INT x, INT y, UINT flags,
|
||||
UINT aa_flags, LPCWSTR str, UINT count, const INT *dx )
|
||||
{
|
||||
dib_info dib;
|
||||
UINT i;
|
||||
DWORD err;
|
||||
BOOL got_pixel;
|
||||
COLORREF fg, bg;
|
||||
DWORD fg_pixel, bg_pixel;
|
||||
struct intensity_range glyph_intensities[17];
|
||||
|
||||
assert( info->bmiHeader.biBitCount > 8 ); /* mono and indexed formats don't support anti-aliasing */
|
||||
|
||||
if (!init_dib_info_from_bitmapinfo( &dib, info, bits->ptr, 0 )) return FALSE;
|
||||
|
||||
fg = make_rgb_colorref( hdc, &dib, GetTextColor( hdc ), &got_pixel, &fg_pixel);
|
||||
if (!got_pixel) fg_pixel = dib.funcs->colorref_to_pixel( &dib, fg );
|
||||
|
||||
get_aa_ranges( fg, glyph_intensities );
|
||||
|
||||
if (flags & ETO_OPAQUE)
|
||||
{
|
||||
rop_mask bkgnd_color;
|
||||
|
||||
bg = make_rgb_colorref( hdc, &dib, GetBkColor( hdc ), &got_pixel, &bg_pixel);
|
||||
if (!got_pixel) bg_pixel = dib.funcs->colorref_to_pixel( &dib, bg );
|
||||
|
||||
bkgnd_color.and = 0;
|
||||
bkgnd_color.xor = bg_pixel;
|
||||
solid_rects( &dib, 1, &src->visrect, &bkgnd_color, 0 );
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
GLYPHMETRICS metrics;
|
||||
struct gdi_image_bits image;
|
||||
|
||||
err = get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, &image );
|
||||
if (err) continue;
|
||||
|
||||
if (image.ptr)
|
||||
{
|
||||
RECT rect, clipped_rect;
|
||||
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;
|
||||
|
||||
rect.left = x + metrics.gmptGlyphOrigin.x;
|
||||
rect.top = y - metrics.gmptGlyphOrigin.y;
|
||||
rect.right = rect.left + metrics.gmBlackBoxX;
|
||||
rect.bottom = rect.top + metrics.gmBlackBoxY;
|
||||
|
||||
if (intersect_rect( &clipped_rect, &rect, &src->visrect ))
|
||||
{
|
||||
src_origin.x = clipped_rect.left - rect.left;
|
||||
src_origin.y = clipped_rect.top - rect.top;
|
||||
|
||||
dib.funcs->draw_glyph( &dib, &clipped_rect, &glyph_dib, &src_origin,
|
||||
fg_pixel, glyph_intensities );
|
||||
}
|
||||
}
|
||||
if (image.free) image.free( &image );
|
||||
|
||||
if (dx)
|
||||
{
|
||||
if (flags & ETO_PDY)
|
||||
{
|
||||
x += dx[ i * 2 ];
|
||||
y += dx[ i * 2 + 1];
|
||||
}
|
||||
else
|
||||
x += dx[ i ];
|
||||
}
|
||||
else
|
||||
{
|
||||
x += metrics.gmCellIncX;
|
||||
y += metrics.gmCellIncY;
|
||||
}
|
||||
}
|
||||
free_dib_info( &dib );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_ExtTextOut
|
||||
*/
|
||||
|
@ -269,7 +364,7 @@ BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
|
|||
GLYPHMETRICS metrics;
|
||||
struct gdi_image_bits image;
|
||||
|
||||
err = get_glyph_bitmap( pdev, (UINT)str[i], aa_flags, &metrics, &image );
|
||||
err = get_glyph_bitmap( dev->hdc, (UINT)str[i], aa_flags, &metrics, &image );
|
||||
if (err) continue;
|
||||
|
||||
if (image.ptr) draw_glyph( pdev, &origin, &metrics, &image );
|
||||
|
|
|
@ -123,12 +123,11 @@ static inline BOOL rgbquad_equal(const RGBQUAD *a, const RGBQUAD *b)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static COLORREF make_rgb_colorref( dibdrv_physdev *pdev, COLORREF color,
|
||||
BOOL *got_pixel, DWORD *pixel )
|
||||
COLORREF make_rgb_colorref( HDC hdc, dib_info *dib, COLORREF color, BOOL *got_pixel, DWORD *pixel )
|
||||
{
|
||||
BYTE type = color >> 24;
|
||||
WORD index = LOWORD( color );
|
||||
HPALETTE pal = GetCurrentObject( pdev->dev.hdc, OBJ_PAL );
|
||||
HPALETTE pal = GetCurrentObject( hdc, OBJ_PAL );
|
||||
PALETTEENTRY pal_ent;
|
||||
|
||||
*pixel = 0;
|
||||
|
@ -143,13 +142,13 @@ static COLORREF make_rgb_colorref( dibdrv_physdev *pdev, COLORREF color,
|
|||
*pixel = 0;
|
||||
color = RGB(0, 0, 0);
|
||||
|
||||
if (pdev->dib.bit_count <= 8 && index < (1 << pdev->dib.bit_count))
|
||||
if (dib->bit_count <= 8 && index < (1 << dib->bit_count))
|
||||
{
|
||||
*pixel = index;
|
||||
if (index < pdev->dib.color_table_size)
|
||||
color = RGB( pdev->dib.color_table[index].rgbRed,
|
||||
pdev->dib.color_table[index].rgbGreen,
|
||||
pdev->dib.color_table[index].rgbBlue );
|
||||
if (index < dib->color_table_size)
|
||||
color = RGB( dib->color_table[index].rgbRed,
|
||||
dib->color_table[index].rgbGreen,
|
||||
dib->color_table[index].rgbBlue );
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -187,7 +186,7 @@ DWORD get_pixel_color( dibdrv_physdev *pdev, COLORREF color, BOOL mono_fixup )
|
|||
DWORD pixel;
|
||||
COLORREF rgb_ref;
|
||||
|
||||
rgb_ref = make_rgb_colorref( pdev, color, &got_pixel, &pixel );
|
||||
rgb_ref = make_rgb_colorref( pdev->dev.hdc, &pdev->dib, color, &got_pixel, &pixel );
|
||||
if (got_pixel) return pixel;
|
||||
|
||||
if (pdev->dib.bit_count != 1 || !mono_fixup)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -1668,6 +1669,44 @@ static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/* helper for nulldrv_ExtTextOut */
|
||||
static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
|
||||
LPCWSTR str, UINT count, const INT *dx )
|
||||
{
|
||||
int i;
|
||||
RECT rect;
|
||||
|
||||
rect.left = rect.top = INT_MAX;
|
||||
rect.right = rect.bottom = INT_MIN;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
GLYPHMETRICS metrics;
|
||||
|
||||
if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
|
||||
|
||||
rect.left = min( rect.left, x + metrics.gmptGlyphOrigin.x );
|
||||
rect.top = min( rect.top, y - metrics.gmptGlyphOrigin.y );
|
||||
rect.right = max( rect.right, x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX );
|
||||
rect.bottom = max( rect.bottom, y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY );
|
||||
|
||||
if (dx)
|
||||
{
|
||||
if (flags & ETO_PDY)
|
||||
{
|
||||
x += dx[ i * 2 ];
|
||||
y += dx[ i * 2 + 1];
|
||||
}
|
||||
else x += dx[ i ];
|
||||
}
|
||||
else
|
||||
{
|
||||
x += metrics.gmCellIncX;
|
||||
y += metrics.gmCellIncY;
|
||||
}
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
/* helper for nulldrv_ExtTextOut */
|
||||
static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
|
||||
const struct gdi_image_bits *image, const RECT *clip )
|
||||
|
@ -1718,7 +1757,8 @@ static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS
|
|||
BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
|
||||
LPCWSTR str, UINT count, const INT *dx )
|
||||
{
|
||||
UINT i;
|
||||
DC *dc = get_nulldrv_dc( dev );
|
||||
UINT aa_flags, i;
|
||||
DWORD err;
|
||||
HGDIOBJ orig;
|
||||
HPEN pen;
|
||||
|
@ -1740,6 +1780,85 @@ BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect
|
|||
|
||||
if (!count) return TRUE;
|
||||
|
||||
aa_flags = get_font_aa_flags( dev->hdc );
|
||||
|
||||
if (aa_flags != GGO_BITMAP)
|
||||
{
|
||||
char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
|
||||
BITMAPINFO *info = (BITMAPINFO *)buffer;
|
||||
struct gdi_image_bits bits;
|
||||
struct bitblt_coords src, dst;
|
||||
PHYSDEV dst_dev;
|
||||
RECT clip;
|
||||
|
||||
dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
|
||||
src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
|
||||
if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
|
||||
if (get_clip_box( dc, &clip )) intersect_rect( &src.visrect, &src.visrect, &clip );
|
||||
if (is_rect_empty( &src.visrect )) return TRUE;
|
||||
|
||||
/* FIXME: check for ETO_OPAQUE and avoid GetImage */
|
||||
src.x = src.visrect.left;
|
||||
src.y = src.visrect.top;
|
||||
src.width = src.visrect.right - src.visrect.left;
|
||||
src.height = src.visrect.bottom - src.visrect.top;
|
||||
dst = src;
|
||||
if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
|
||||
(src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
|
||||
{
|
||||
/* we can avoid the GetImage, just query the needed format */
|
||||
memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
|
||||
info->bmiHeader.biSize = sizeof(info->bmiHeader);
|
||||
info->bmiHeader.biWidth = src.width;
|
||||
info->bmiHeader.biHeight = -src.height;
|
||||
err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, NULL, NULL, NULL, 0 );
|
||||
if (!err || err == ERROR_BAD_FORMAT)
|
||||
{
|
||||
/* make the source rectangle relative to the source bits */
|
||||
src.x = src.y = 0;
|
||||
src.visrect.left = src.visrect.top = 0;
|
||||
src.visrect.right = src.width;
|
||||
src.visrect.bottom = src.height;
|
||||
|
||||
bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
|
||||
if (!bits.ptr) return ERROR_OUTOFMEMORY;
|
||||
bits.is_copy = TRUE;
|
||||
bits.free = free_heap_bits;
|
||||
err = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
|
||||
err = src_dev->funcs->pGetImage( src_dev, 0, info, &bits, &src );
|
||||
if (!err && !bits.is_copy)
|
||||
{
|
||||
void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
|
||||
if (!ptr)
|
||||
{
|
||||
if (bits.free) bits.free( &bits );
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
memcpy( ptr, bits.ptr, get_dib_image_size( info ));
|
||||
if (bits.free) bits.free( &bits );
|
||||
bits.ptr = ptr;
|
||||
bits.is_copy = TRUE;
|
||||
bits.free = free_heap_bits;
|
||||
}
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
/* make x,y relative to the image bits */
|
||||
x += src.visrect.left - dst.visrect.left;
|
||||
y += src.visrect.top - dst.visrect.top;
|
||||
render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
|
||||
aa_flags, str, count, dx );
|
||||
err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
|
||||
if (bits.free) bits.free( &bits );
|
||||
return !err;
|
||||
}
|
||||
}
|
||||
|
||||
pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
|
||||
orig = SelectObject( dev->hdc, pen );
|
||||
|
||||
|
|
|
@ -266,6 +266,9 @@ 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,
|
||||
const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst,
|
||||
BLENDFUNCTION blend ) DECLSPEC_HIDDEN;
|
||||
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,
|
||||
UINT aa_flags, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* driver.c */
|
||||
extern const struct gdi_dc_funcs null_driver DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Reference in a new issue