Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net --- By setting the appropriate gamma value, subpixel color fringing reduced. https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT...
dlls/gdi32/dc.c | 1 + dlls/gdi32/dibdrv/dibdrv.h | 9 ++++++- dlls/gdi32/dibdrv/graphics.c | 38 ++++++++++++++++++++++---- dlls/gdi32/dibdrv/primitives.c | 49 +++++++++++++++++++++++++--------- dlls/gdi32/font.c | 28 +++++++++++++++++++ dlls/gdi32/gdi_private.h | 1 + 6 files changed, 108 insertions(+), 18 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 892d3e9744..dd7a86d571 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -87,6 +87,7 @@ static void set_initial_dc_state( DC *dc ) dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */ dc->layout = 0; dc->font_code_page = CP_ACP; + dc->font_gamma = 0; dc->ROPmode = R2_COPYPEN; dc->polyFillMode = ALTERNATE; dc->stretchBltMode = BLACKONWHITE; diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index f79f5b0867..ea33386faf 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -85,6 +85,13 @@ struct intensity_range BYTE b_min, b_max; };
+struct font_gamma_lut +{ + DWORD value; + BYTE encode[256]; + BYTE decode[256]; +}; + typedef struct dibdrv_physdev { struct gdi_physdev dev; @@ -192,7 +199,7 @@ typedef struct primitive_funcs void (* draw_glyph)(const dib_info *dst, const RECT *rc, const dib_info *glyph, const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges); void (* draw_subpixel_glyph)(const dib_info *dst, const RECT *rc, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ); + const POINT *origin, DWORD text_pixel, const struct font_gamma_lut *gamma); DWORD (* get_pixel)(const dib_info *dib, int x, int y); DWORD (* colorref_to_pixel)(const dib_info *dib, COLORREF color); COLORREF (* pixel_to_colorref)(const dib_info *dib, DWORD pixel); diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c index 08f8c3d6d2..195866b92f 100644 --- a/dlls/gdi32/dibdrv/graphics.c +++ b/dlls/gdi32/dibdrv/graphics.c @@ -683,7 +683,7 @@ static inline void get_text_bkgnd_masks( DC *dc, const dib_info *dib, rop_mask *
static void draw_glyph( dib_info *dib, int x, int y, const GLYPHMETRICS *metrics, const dib_info *glyph_dib, DWORD text_color, - const struct intensity_range *ranges, const struct clipped_rects *clipped_rects, + const void *lut, const struct clipped_rects *clipped_rects, RECT *bounds ) { int i; @@ -705,10 +705,10 @@ static void draw_glyph( dib_info *dib, int x, int y, const GLYPHMETRICS *metrics
if (glyph_dib->bit_count == 32) dib->funcs->draw_subpixel_glyph( dib, &clipped_rect, glyph_dib, &src_origin, - text_color ); + text_color, lut ); else dib->funcs->draw_glyph( dib, &clipped_rect, glyph_dib, &src_origin, - text_color, ranges ); + text_color, lut ); } } } @@ -808,6 +808,19 @@ done: return add_cached_glyph( font, index, flags, glyph ); }
+static inline void update_font_gamma_lut( DWORD value, struct font_gamma_lut *gamma ) +{ + int i; + + for ( i = 0; i < 256; i++ ) + { + gamma->encode[i] = pow( i / 255., 1000. / value ) * 255. + .5; + gamma->decode[i] = pow( i / 255., value / 1000. ) * 255. + .5; + } + + gamma->value = value; +} + static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT x, INT y, UINT flags, const WCHAR *str, UINT count, const INT *dx, const struct clipped_rects *clipped_rects, RECT *bounds ) @@ -817,6 +830,8 @@ static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT dib_info glyph_dib; DWORD text_color; struct intensity_range ranges[17]; + static struct font_gamma_lut gamma; + void *lut = NULL;
glyph_dib.bit_count = get_glyph_depth( font->aa_flags ); glyph_dib.rect.left = 0; @@ -826,8 +841,21 @@ static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT
text_color = get_pixel_color( dc, dib, dc->textColor, TRUE );
- if (glyph_dib.bit_count == 8) + switch ( glyph_dib.bit_count ) + { + case 8: get_aa_ranges( dib->funcs->pixel_to_colorref( dib, text_color ), ranges ); + lut = ranges; + break; + case 32: + if ( gamma.value != dc->font_gamma ) + { + update_font_gamma_lut( dc->font_gamma, &gamma ); + TRACE( "font_contrast = %d\n", gamma.value ); + } + lut = γ + break; + }
for (i = 0; i < count; i++) { @@ -841,7 +869,7 @@ static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT glyph_dib.stride = get_dib_stride( glyph->metrics.gmBlackBoxX, glyph_dib.bit_count ); glyph_dib.bits.ptr = glyph->bits;
- draw_glyph( dib, x, y, &glyph->metrics, &glyph_dib, text_color, ranges, clipped_rects, bounds ); + draw_glyph( dib, x, y, &glyph->metrics, &glyph_dib, text_color, lut, clipped_rects, bounds );
if (dx) { diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c index 0d097b2da6..2be3fcf3f1 100644 --- a/dlls/gdi32/dibdrv/primitives.c +++ b/dlls/gdi32/dibdrv/primitives.c @@ -6272,16 +6272,35 @@ static void draw_glyph_null( const dib_info *dib, const RECT *rect, const dib_in { return; } +static inline BYTE blend_color_gamma( BYTE dst, BYTE text, BYTE alpha, + const struct font_gamma_lut *gamma ) +{ + if ( alpha == 0 ) return dst; + if ( alpha == 255 ) return text; + if ( dst == text ) return dst; + + return gamma->encode[ blend_color( gamma->decode[dst], + gamma->decode[text], + alpha) ]; +}
-static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha ) +static inline DWORD blend_subpixel( BYTE r, BYTE g, BYTE b, DWORD text, DWORD alpha, + const struct font_gamma_lut *gamma ) { + if ( gamma != NULL && gamma->value != 1000 ) + { + return blend_color_gamma( r, text >> 16, (BYTE)(alpha >> 16), gamma ) << 16 | + blend_color_gamma( g, text >> 8, (BYTE)(alpha >> 8), gamma ) << 8 | + blend_color_gamma( b, text, (BYTE) alpha, gamma ); + } return blend_color( r, text >> 16, (BYTE)(alpha >> 16) ) << 16 | blend_color( g, text >> 8, (BYTE)(alpha >> 8) ) << 8 | blend_color( b, text, (BYTE) alpha ); }
static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ) + const POINT *origin, DWORD text_pixel, + const struct font_gamma_lut *gamma ) { DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top ); const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y ); @@ -6292,7 +6311,8 @@ static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, con for (x = 0; x < rect->right - rect->left; x++) { if (glyph_ptr[x] == 0) continue; - dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], text_pixel, glyph_ptr[x] ); + dst_ptr[x] = blend_subpixel( dst_ptr[x] >> 16, dst_ptr[x] >> 8, dst_ptr[x], + text_pixel, glyph_ptr[x], gamma ); } dst_ptr += dib->stride / 4; glyph_ptr += glyph->stride / 4; @@ -6300,7 +6320,8 @@ static void draw_subpixel_glyph_8888( const dib_info *dib, const RECT *rect, con }
static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ) + const POINT *origin, DWORD text_pixel, + const struct font_gamma_lut *gamma ) { DWORD *dst_ptr = get_pixel_ptr_32( dib, rect->left, rect->top ); const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y ); @@ -6319,7 +6340,7 @@ static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len), get_field(dst_ptr[x], dib->green_shift, dib->green_len), get_field(dst_ptr[x], dib->blue_shift, dib->blue_len), - text, glyph_ptr[x] ); + text, glyph_ptr[x], gamma ); dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } dst_ptr += dib->stride / 4; @@ -6328,7 +6349,8 @@ static void draw_subpixel_glyph_32( const dib_info *dib, const RECT *rect, const }
static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ) + const POINT *origin, DWORD text_pixel, + const struct font_gamma_lut *gamma ) { BYTE *dst_ptr = get_pixel_ptr_24( dib, rect->left, rect->top ); const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y ); @@ -6341,7 +6363,7 @@ static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const { if (glyph_ptr[x] == 0) continue; val = blend_subpixel( dst_ptr[x * 3 + 2], dst_ptr[x * 3 + 1], dst_ptr[x * 3], - text_pixel, glyph_ptr[x] ); + text_pixel, glyph_ptr[x], gamma ); dst_ptr[x * 3] = val; dst_ptr[x * 3 + 1] = val >> 8; dst_ptr[x * 3 + 2] = val >> 16; @@ -6352,7 +6374,8 @@ static void draw_subpixel_glyph_24( const dib_info *dib, const RECT *rect, const }
static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ) + const POINT *origin, DWORD text_pixel, + const struct font_gamma_lut *gamma ) { WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top ); const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y ); @@ -6371,7 +6394,7 @@ static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, cons val = blend_subpixel( ((dst_ptr[x] >> 7) & 0xf8) | ((dst_ptr[x] >> 12) & 0x07), ((dst_ptr[x] >> 2) & 0xf8) | ((dst_ptr[x] >> 7) & 0x07), ((dst_ptr[x] << 3) & 0xf8) | ((dst_ptr[x] >> 2) & 0x07), - text, glyph_ptr[x] ); + text, glyph_ptr[x], NULL ); dst_ptr[x] = ((val >> 9) & 0x7c00) | ((val >> 6) & 0x03e0) | ((val >> 3) & 0x001f); } dst_ptr += dib->stride / 2; @@ -6380,7 +6403,8 @@ static void draw_subpixel_glyph_555( const dib_info *dib, const RECT *rect, cons }
static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ) + const POINT *origin, DWORD text_pixel, + const struct font_gamma_lut *gamma ) { WORD *dst_ptr = get_pixel_ptr_16( dib, rect->left, rect->top ); const DWORD *glyph_ptr = get_pixel_ptr_32( glyph, origin->x, origin->y ); @@ -6399,7 +6423,7 @@ static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const val = blend_subpixel( get_field(dst_ptr[x], dib->red_shift, dib->red_len), get_field(dst_ptr[x], dib->green_shift, dib->green_len), get_field(dst_ptr[x], dib->blue_shift, dib->blue_len), - text, glyph_ptr[x] ); + text, glyph_ptr[x], NULL ); dst_ptr[x] = rgb_to_pixel_masks( dib, val >> 16, val >> 8, val ); } dst_ptr += dib->stride / 2; @@ -6408,7 +6432,8 @@ static void draw_subpixel_glyph_16( const dib_info *dib, const RECT *rect, const }
static void draw_subpixel_glyph_null( const dib_info *dib, const RECT *rect, const dib_info *glyph, - const POINT *origin, DWORD text_pixel ) + const POINT *origin, DWORD text_pixel, + const struct font_gamma_lut *gamma ) { return; } diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 5c67d5b518..90dcf178de 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -729,6 +729,33 @@ static void update_font_code_page( DC *dc, HANDLE font ) TRACE("charset %d => cp %d\n", charset, dc->font_code_page); }
+static void update_font_gamma( DC *dc ) +{ + static const WCHAR desktopW[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\', + 'D','e','s','k','t','o','p',0 }; + static const WCHAR smoothing_gamma[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g', + 'G','a','m','m','a',0}; + static BOOL need_update = TRUE; + const DWORD gamma_default = 1000; /* FIXME 1400 */ + static DWORD gamma = gamma_default; + HKEY key; + + if ( need_update && + RegOpenKeyW( HKEY_CURRENT_USER, desktopW, &key ) == ERROR_SUCCESS ) + { + if ( get_key_value( key, smoothing_gamma, &gamma ) || gamma == 0 ) + gamma = gamma_default; + RegCloseKey( key ); + + gamma = min( max( gamma, 1000), 2200 ); + need_update = FALSE; + } + + dc->font_gamma = gamma; + + TRACE("font_gamma %d\n", dc->font_gamma); +} + /*********************************************************************** * FONT_SelectObject */ @@ -754,6 +781,7 @@ static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc ) dc->hFont = handle; dc->aa_flags = aa_flags ? aa_flags : GGO_BITMAP; update_font_code_page( dc, handle ); + update_font_gamma( dc ); GDI_dec_ref_count( ret ); } else GDI_dec_ref_count( handle ); diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 5b09b84846..da8e6f32ef 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -100,6 +100,7 @@ typedef struct tagDC struct gdi_path *path;
UINT font_code_page; + DWORD font_gamma; WORD ROPmode; WORD polyFillMode; WORD stretchBltMode;
On Sat, Oct 13, 2018 at 01:08:06AM +0900, Byeongsik Jeon wrote:
Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net
By setting the appropriate gamma value, subpixel color fringing reduced. https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT...
dlls/gdi32/dc.c | 1 + dlls/gdi32/dibdrv/dibdrv.h | 9 ++++++- dlls/gdi32/dibdrv/graphics.c | 38 ++++++++++++++++++++++---- dlls/gdi32/dibdrv/primitives.c | 49 +++++++++++++++++++++++++--------- dlls/gdi32/font.c | 28 +++++++++++++++++++ dlls/gdi32/gdi_private.h | 1 + 6 files changed, 108 insertions(+), 18 deletions(-)
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 892d3e9744..dd7a86d571 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -87,6 +87,7 @@ static void set_initial_dc_state( DC *dc ) dc->miterLimit = 10.0f; /* 10.0 is the default, from MSDN */ dc->layout = 0; dc->font_code_page = CP_ACP;
- dc->font_gamma = 0; dc->ROPmode = R2_COPYPEN; dc->polyFillMode = ALTERNATE; dc->stretchBltMode = BLACKONWHITE;
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index f79f5b0867..ea33386faf 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -85,6 +85,13 @@ struct intensity_range BYTE b_min, b_max; };
+struct font_gamma_lut +{
- DWORD value;
- BYTE encode[256];
- BYTE decode[256];
+};
typedef struct dibdrv_physdev { struct gdi_physdev dev; @@ -192,7 +199,7 @@ typedef struct primitive_funcs void (* draw_glyph)(const dib_info *dst, const RECT *rc, const dib_info *glyph, const POINT *origin, DWORD text_pixel, const struct intensity_range *ranges); void (* draw_subpixel_glyph)(const dib_info *dst, const RECT *rc, const dib_info *glyph,
const POINT *origin, DWORD text_pixel );
DWORD (* get_pixel)(const dib_info *dib, int x, int y); DWORD (* colorref_to_pixel)(const dib_info *dib, COLORREF color); COLORREF (* pixel_to_colorref)(const dib_info *dib, DWORD pixel);const POINT *origin, DWORD text_pixel, const struct font_gamma_lut *gamma);
diff --git a/dlls/gdi32/dibdrv/graphics.c b/dlls/gdi32/dibdrv/graphics.c index 08f8c3d6d2..195866b92f 100644 --- a/dlls/gdi32/dibdrv/graphics.c +++ b/dlls/gdi32/dibdrv/graphics.c @@ -683,7 +683,7 @@ static inline void get_text_bkgnd_masks( DC *dc, const dib_info *dib, rop_mask *
static void draw_glyph( dib_info *dib, int x, int y, const GLYPHMETRICS *metrics, const dib_info *glyph_dib, DWORD text_color,
const struct intensity_range *ranges, const struct clipped_rects *clipped_rects,
const void *lut, const struct clipped_rects *clipped_rects, RECT *bounds )
Using a void ptr here is ugly, want you want is a union of the two sets of data.
{ int i; @@ -705,10 +705,10 @@ static void draw_glyph( dib_info *dib, int x, int y, const GLYPHMETRICS *metrics
if (glyph_dib->bit_count == 32) dib->funcs->draw_subpixel_glyph( dib, &clipped_rect, glyph_dib, &src_origin,
text_color );
text_color, lut ); else dib->funcs->draw_glyph( dib, &clipped_rect, glyph_dib, &src_origin,
text_color, ranges );
}text_color, lut ); }
} @@ -808,6 +808,19 @@ done: return add_cached_glyph( font, index, flags, glyph ); }
+static inline void update_font_gamma_lut( DWORD value, struct font_gamma_lut *gamma ) +{
- int i;
- for ( i = 0; i < 256; i++ )
- {
gamma->encode[i] = pow( i / 255., 1000. / value ) * 255. + .5;
gamma->decode[i] = pow( i / 255., value / 1000. ) * 255. + .5;
- }
- gamma->value = value;
+}
static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT x, INT y, UINT flags, const WCHAR *str, UINT count, const INT *dx, const struct clipped_rects *clipped_rects, RECT *bounds ) @@ -817,6 +830,8 @@ static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT dib_info glyph_dib; DWORD text_color; struct intensity_range ranges[17];
static struct font_gamma_lut gamma;
void *lut = NULL;
glyph_dib.bit_count = get_glyph_depth( font->aa_flags ); glyph_dib.rect.left = 0;
@@ -826,8 +841,21 @@ static void render_string( DC *dc, dib_info *dib, struct cached_font *font, INT
text_color = get_pixel_color( dc, dib, dc->textColor, TRUE );
- if (glyph_dib.bit_count == 8)
- switch ( glyph_dib.bit_count )
- {
- case 8: get_aa_ranges( dib->funcs->pixel_to_colorref( dib, text_color ), ranges );
lut = ranges;
break;
- case 32:
if ( gamma.value != dc->font_gamma )
This isn't thread safe, you should store the computed values in the dc.
{
update_font_gamma_lut( dc->font_gamma, &gamma );
TRACE( "font_contrast = %d\n", gamma.value );
}
lut = γ
break;
}
for (i = 0; i < count; i++) {