Шрифты. Тонкая подстройка субпиксельной отрисовки (увеличиваем четкость, избавляемся от цветной мазни, желтого гало и т.п)

Полезные советы и программы от пользователей нашего форума.

Модератор: Модераторы разделов

Lifter
Сообщения: 7
ОС: GNU/Linux

Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение Lifter »

Не вдаваясь в подробности (см. http://www.grc.com/cttech.htm и ссылки в конце поста) отмечу, что качество субъективного восприятия субпиксельного рендеринга в значительной степени зависит от некоего фильтра, который отвечает за «размазывание» интенсивности одного субпикселя по соседним субпикселям. Делается это для уменьшения локального цветового дисбаланса, который легко заметен невооруженным глазом.
Про влияние глаз, монитора (dpi прежде всего) и т.п. не будем, ибо итак понятно. С высоким дпи, вероятно, любой метод сглаживания смотрится отлично. :)

По-умолчанию во freetype используется фильтр { 0x10, 0x40, 0x70, 0x40, 0x10 }, который должен неплохо работать на большинстве ЖК-дисплеев (по мнению разработчиков freetype?).

В ранних версиях даже была возможность изменять веса фильтра.
* filter_weights :: a pointer to an array of 5 bytes corresponding
* to the weights of a 5-tap FIR filter. Each
* weight must be positive, and their sum should
* be at least 256 to avoid loss of darkness
* in the rendered glyphs. The sum can be greater
* than 256 to darken the glyphs (el-cheapo gamma)


Сумма значений должна быть 256, для избежания осветления или затемнения шрифта.

На _моем_ мониторе и _моими_ глазами лучше и четче выглядит фильтр { 8, 28, 100, 80, 40 }. Во всяком случае пока-что остановился на нем.

freetype-2.3.7-filter_weights_8_28_100_80_40.diff

Код:

diff -ru freetype-2.3.7.original/src/base/ftlcdfil.c freetype-2.3.7.patched/src/base/ftlcdfil.c --- freetype-2.3.7.original/src/base/ftlcdfil.c 2008-01-18 07:19:35.000000000 +0300 +++ freetype-2.3.7.patched/src/base/ftlcdfil.c 2009-01-25 22:08:21.000000000 +0300 @@ -275,7 +275,7 @@ /* the values here sum up to a value larger than 256, */ /* providing a cheap gamma correction */ static const FT_Byte default_filter[5] = - { 0x10, 0x40, 0x70, 0x40, 0x10 }; + { 8, 28, 100, 80, 40 }; if ( library == NULL )


Патчим freetype (http://ftp.twaren.net/Unix/NonGNU/freetype...e-2.3.8.tar.bz2) любимыми вещами вроде bci, включаем subpixel, кладем патч на веса или меняем руками. (Cairo и libXft все как обычно — кладем cleartype-like патчи). Собираем. Кладем полученный libfreetype.so.6 или ссылку на него в нужное место (/usr/lib вероятно), перезапускаем тестируемое приложение (или иксы) либо делаем LD_PRELOAD. Смотрим результат.
Можно подобрать оптимальный для себя вариант и таким способом, что крайне неудобно.

Для удобства можно использовать следующие патчи на ftdiff и ftview из пакета ft2demos (http://ftp.twaren.net/Unix/NonGNU/freetype...s-2.3.8.tar.bz2). Добавлена возможность крутить субпиксельный фильтр.

Для их работы требуется также немного пропатчить freetype. С рабочего варианта для чистоты можно откатить. )

freetype-2.3.8-set_lcd_filter_weights-20090127.diff

Код:

diff -ru freetype-2.3.8.original/include/freetype/ftlcdfil.h freetype-2.3.8.patched/include/freetype/ftlcdfil.h --- freetype-2.3.8.original/include/freetype/ftlcdfil.h 2008-09-12 09:44:39.000000000 +0400 +++ freetype-2.3.8.patched/include/freetype/ftlcdfil.h 2009-01-27 15:07:18.000000000 +0300 @@ -161,6 +161,10 @@ FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ); + FT_EXPORT( FT_Error ) + FT_Library_SetLcdFilterWeights(FT_Library library, + unsigned char *weights); + /* */ diff -ru freetype-2.3.8.original/src/base/ftlcdfil.c freetype-2.3.8.patched/src/base/ftlcdfil.c --- freetype-2.3.8.original/src/base/ftlcdfil.c 2009-01-12 22:13:31.000000000 +0300 +++ freetype-2.3.8.patched/src/base/ftlcdfil.c 2009-01-27 15:14:40.000000000 +0300 @@ -267,6 +267,14 @@ FT_EXPORT_DEF( FT_Error ) + FT_Library_SetLcdFilterWeights(FT_Library library, + unsigned char *weights) + { + ft_memcpy(library->lcd_weights, weights, 5); + } + + + FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) { @@ -336,6 +344,17 @@ #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ FT_EXPORT_DEF( FT_Error ) + FT_Library_SetLcdFilterWeights(FT_Library library, + unsigned char *weights) + { + FT_UNUSED( library ); + FT_UNUSED( weights ); + + return FT_Err_Unimplemented_Feature; + } + + + FT_EXPORT_DEF( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ) {


Патчи на ft2demos.

ft2demos-2.3.8-ftdiff-filter_weights_tuner-20090127.diff

Код:

--- ft2demos-2.3.8.original/src/ftdiff.c 2009-01-07 11:16:41.000000000 +0300 +++ ft2demos-2.3.8.patched/src/ftdiff.c 2009-01-27 15:51:42.000000000 +0300 @@ -149,6 +149,10 @@ FT_LcdFilter lcd_filter; HintMode hint_mode; DisplayMode disp_mode; + + int use_custom_lcd_filter; + unsigned char filter_weights[5]; + int fw_index; } ColumnStateRec, *ColumnState; @@ -204,14 +208,19 @@ state->columns[0].use_global_advance_width = 1; state->columns[0].lcd_filter = FT_LCD_FILTER_DEFAULT; state->columns[0].hint_mode = HINT_MODE_BYTECODE; + state->columns[0].use_custom_lcd_filter = 0; + //freetype default filter weights + memcpy(state->columns[0].filter_weights, "\x10\x40\x70\x40\x10", 5); + state->columns[0].fw_index = 2; state->columns[1] = state->columns[0]; state->columns[1].hint_mode = HINT_MODE_AUTOHINT; + state->columns[1].use_custom_lcd_filter = 1; state->columns[2] = state->columns[0]; state->columns[2].hint_mode = HINT_MODE_UNHINTED; - state->col = 2; + state->col = 1; if ( FT_Init_FreeType( &state->library ) != 0 ) panic( "could not initialize FreeType library. Check your code\n" ); @@ -430,6 +439,10 @@ if ( column->use_lcd_filter ) FT_Library_SetLcdFilter( face->glyph->library, column->lcd_filter ); + if (column->use_custom_lcd_filter) + FT_Library_SetLcdFilterWeights(face->glyph->library, column->filter_weights); + /* memcpy((unsigned char*)face->glyph->library->lcd_weights, column->filter_weights, 5); */ + y += state->size->metrics.ascender / 64; line_height = state->size->metrics.height / 64; @@ -578,6 +591,19 @@ if ( !column->use_lcd_filter ) msg = "gray rendering"; + else if (column->use_custom_lcd_filter) + { + msg = ""; + int fwi = column->fw_index; + unsigned char *fw = column->filter_weights; + sprintf(temp, "%s%d%s%s%d%s%s%d%s%s%d%s%s%d%s", + fwi == 0 ? "[" : " ", fw[0], fwi == 0 ? "]" : " ", + fwi == 1 ? "[" : " ", fw[1], fwi == 1 ? "]" : " ", + fwi == 2 ? "[" : " ", fw[2], fwi == 2 ? "]" : " ", + fwi == 3 ? "[" : " ", fw[3], fwi == 3 ? "]" : " ", + fwi == 4 ? "[" : " ", fw[4], fwi == 4 ? "]" : " "); + state->display.disp_text(disp, left, bottom + 15, temp); + } else switch ( column->lcd_filter ) { case FT_LCD_FILTER_NONE: @@ -808,6 +834,9 @@ grWriteln( " h : toggle hinting mode" ); grWriteln( " k : toggle kerning" ); grWriteln( " l : change LCD filter type" ); + grWriteln( " [, ] : select filter weight in custom lcd filter mode" ); + grWriteln( " -, +(=) : increase/decrease selected lcd filter weight value"); + grWriteln( " : in custom lcd filter mode"); grWriteln( " r : toggle rendering mode" ); grWriteln( " Up : increase pointsize by 0.5 unit" ); grWriteln( " Down : decrease pointsize by 0.5 unit" ); @@ -963,8 +992,17 @@ break; case FT_LCD_FILTER_DEFAULT: - column->lcd_filter = FT_LCD_FILTER_LIGHT; - state->message = (char *)"using light LCD filter"; + if (!column->use_custom_lcd_filter) + { + column->use_custom_lcd_filter = 1; + state->message = (char*)"using custom lcd filter"; + } + else + { + column->use_custom_lcd_filter = 0; + column->lcd_filter = FT_LCD_FILTER_LIGHT; + state->message = (char *)"using light LCD filter"; + } break; case FT_LCD_FILTER_LIGHT: @@ -1002,6 +1040,35 @@ event_change_gamma( state, -0.1 ); break; + case grKEY('['): + if (!column->use_custom_lcd_filter) + break; + column->fw_index -= 1; + if (column->fw_index < 0) + column->fw_index = 4; + break; + + case grKEY(']'): + if (!column->use_custom_lcd_filter) + break; + column->fw_index += 1; + if (column->fw_index > 4) + column->fw_index = 0; + break; + + case grKEY('-'): + if (!column->use_custom_lcd_filter) + break; + column->filter_weights[column->fw_index] -= 1; + break; + + case grKEY('+'): + case grKEY('='): + if (!column->use_custom_lcd_filter) + break; + column->filter_weights[column->fw_index] += 1; + break; + default: break; }


ft2demos-2.3.7-ftview-filter_weights_tuner-20090125.diff

Код:

--- ft2demos-2.3.7.original/src/ftview.c 2007-12-30 00:50:11.000000000 +0300 +++ ft2demos-2.3.7-mypatch/src/ftview.c 2009-01-25 18:55:00.000000000 +0300 @@ -38,7 +38,7 @@ #define INIT_SIZE( size, start_x, start_y, step_x, step_y, x, y ) \ do { \ start_x = 4; \ - start_y = CEIL( size->metrics.height ) + 2 * HEADER_HEIGHT; \ + start_y = CEIL( size->metrics.height ) + 3 * HEADER_HEIGHT; \ step_x = CEIL( size->metrics.max_advance ); \ step_y = CEIL( size->metrics.height ) + 4; \ \ @@ -86,7 +86,12 @@ int Fail; int preload; - } status = { RENDER_MODE_ALL, FT_ENCODING_NONE, 72, 48, -1, 1.0, 0, 0, 0, 0, 0, NULL, { 0 }, 0, 0 }; + int use_custom_lcd_filter; + unsigned char filter_weights[5]; + int fw_index; + + } status = { RENDER_MODE_ALL, FT_ENCODING_NONE, 72, 48, -1, 1.0, 0, 0, 0, 0, 0, NULL, { 0 }, 0, 0, + 0, "\x10\x40\x70\x40\x10", 2}; static FTDemo_Display* display; @@ -376,23 +381,29 @@ { int gindex; - if ( handle->encoding == FT_ENCODING_NONE ) gindex = i; else gindex = FTDemo_Get_Index( handle, i ); - error = FTDemo_Draw_Index( handle, display, gindex, &x, &y ); - if ( error ) - status.Fail++; - else if ( X_TOO_LONG( x, size, display ) ) - { - x = start_x; - y += step_y; - - if ( Y_TOO_LONG( y, size, display ) ) - break; - } + FT_Face face = size->face; + error = FT_Load_Glyph( face, gindex, handle->load_flags ); + if (error ) + status.Fail++; + else + { + error = FTDemo_Draw_Slot( handle, display, face->glyph, &x, &y ); + if ( error ) + status.Fail++; + else if ( X_TOO_LONG( x, size, display ) ) + { + x = start_x; + y += step_y; + + if ( Y_TOO_LONG( y, size, display ) ) + break; + } + } i++; } @@ -440,23 +451,30 @@ gindex = FTDemo_Get_Index( handle, *p ); - error = FTDemo_Draw_Index( handle, display, gindex, &x, &y ); - if ( error ) - status.Fail++; + FT_Face face = size->face; + error = FT_Load_Glyph( face, gindex, handle->load_flags ); + if (error) + status.Fail++; else - { - /* Draw_Index adds one pixel space */ - x--; - - if ( X_TOO_LONG( x, size, display ) ) - { - x = start_x; - y += step_y; - - if ( Y_TOO_LONG( y, size, display ) ) - break; - } - } + { + error = FTDemo_Draw_Slot( handle, display, face->glyph, &x, &y ); + if ( error ) + status.Fail++; + else + { + /* Draw_Index adds one pixel space */ + x--; + + if ( X_TOO_LONG( x, size, display ) ) + { + x = start_x; + y += step_y; + + if ( Y_TOO_LONG( y, size, display ) ) + break; + } + } + } p++; @@ -503,7 +521,7 @@ } start_x = 4; - start_y = 2 * HEADER_HEIGHT; + start_y = 3 * HEADER_HEIGHT; for ( pt_size = first_size; pt_size < max_size; pt_size += 64 ) { @@ -540,11 +558,18 @@ gindex = FTDemo_Get_Index( handle, *p ); - error = FTDemo_Draw_Index( handle, display, gindex, &x, &y ); - if ( error ) - status.Fail++; - else if ( X_TOO_LONG( x, size, display ) ) - break; + FT_Face face = size->face; + error = FT_Load_Glyph( face, gindex, handle->load_flags ); + if (error) + status.Fail++; + else + { + error = FTDemo_Draw_Slot( handle, display, face->glyph, &x, &y ); + if ( error ) + status.Fail++; + else if ( X_TOO_LONG( x, size, display ) ) + break; + } p++; } @@ -595,6 +620,12 @@ grWriteln( " space : toggle rendering mode" ); grWriteln( " 1-6 : select rendering mode" ); grLn(); + grWriteln( " F : toggle custom lcd filter mode" ); + grWriteln( " [, ] : select filter weight in custom lcd filter" ); + grWriteln( " : mode" ); + grWriteln( " -, +(=) : increase/decrease selected lcd filter weight" ); + grWriteln( " : value in custom lcd filter mode"); + grLn(); grWriteln( " G : show gamma ramp" ); grWriteln( " g : increase gamma by 0.1" ); grWriteln( " v : decrease gamma by 0.1" ); @@ -938,8 +969,51 @@ case grKeyF11: event_index_change( -1000 ); break; case grKeyF12: event_index_change( 1000 ); break; + case grKEY( 'F' ): + status.use_custom_lcd_filter = ! status.use_custom_lcd_filter; + if (status.use_custom_lcd_filter) + FT_Library_SetLcdFilterWeights(handle->library, status.filter_weights); + else + FT_Library_SetLcdFilterWeights(handle->library, (unsigned char*)"\x10\x40\x70\x40\x10"); + status.header = status.use_custom_lcd_filter + ? (char *)"using custom lcd filter weights" + : (char *)"using default lcd filter"; + break; + + case grKEY('['): + if (!status.use_custom_lcd_filter) + break; + status.fw_index -= 1; + if (status.fw_index < 0) + status.fw_index = 4; + break; + + case grKEY(']'): + if (!status.use_custom_lcd_filter) + break; + status.fw_index += 1; + if (status.fw_index > 4) + status.fw_index = 0; + break; + + case grKEY('-'): + if (!status.use_custom_lcd_filter) + break; + status.filter_weights[status.fw_index] -= 1; + FT_Library_SetLcdFilterWeights(handle->library, status.filter_weights); + break; + + case grKEY('+'): + case grKEY('='): + if (!status.use_custom_lcd_filter) + break; + status.filter_weights[status.fw_index] += 1; + FT_Library_SetLcdFilterWeights(handle->library, status.filter_weights); + break; + + default: - ; + break; } return ret; @@ -1021,6 +1095,20 @@ grWriteCellString( display->bitmap, 0, HEADER_HEIGHT, status.header_buffer, display->fore_color ); + if (status.use_custom_lcd_filter) + { + int fwi = status.fw_index; + unsigned char *fw = status.filter_weights; + sprintf(status.header_buffer, "%s%d%s%s%d%s%s%d%s%s%d%s%s%d%s", + fwi == 0 ? "[" : " ", fw[0], fwi == 0 ? "]" : " ", + fwi == 1 ? "[" : " ", fw[1], fwi == 1 ? "]" : " ", + fwi == 2 ? "[" : " ", fw[2], fwi == 2 ? "]" : " ", + fwi == 3 ? "[" : " ", fw[3], fwi == 3 ? "]" : " ", + fwi == 4 ? "[" : " ", fw[4], fwi == 4 ? "]" : " "); + grWriteCellString( display->bitmap, 0, 2 * HEADER_HEIGHT, + status.header_buffer, display->fore_color ); + } + grRefreshSurface( display->surface ); } @@ -1179,6 +1267,9 @@ /* Initialize engine */ handle = FTDemo_New( status.encoding ); + handle->lcd_mode = 2; + handle->autohint = 1; + FT_Library_SetLcdFilter( handle->library, FT_LCD_FILTER_DEFAULT ); if ( status.preload )


Собираем согласно ft2demos/README

При запуске не забываем указывать свои реальные значения dpi, или что у вас там в иксах прописано, иначе подобранный вариант будет отличаться от реального рабочего (ключик -r). Примерно так (у меня 84 дпи — девятнашка 1280х1024):

Код: Выделить всё

./bin/ftdiff -r 84 -s 12 /usr/local/share/fonts/VTTF/SegoeRg.ttf /usr/local/share/fonts/VTTF/calibri.ttf &

./bin/ftview -r 84 12 /usr/local/share/fonts/VTTF/SegoeRg.ttf &


После запуска жмем F1 для ознакомления с управлением. И не забываем про второй основной инструмент после глаз — kmag.

Подобранными таким образом значениями фильтра патчим freetype для повседневного, так сказать, использования.

Параметры fonts.conf

Код:

<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> <match target="font" > <edit mode="assign" name="rgba" > <const>rgb</const> </edit> </match> <match target="font" > <edit mode="assign" name="autohint" > <bool>true</bool> </edit> </match> <match target="font" > <edit mode="assign" name="hinting" > <bool>true</bool> </edit> </match> <match target="font" > <edit mode="assign" name="hintstyle" > <const>hintfull</const> </edit> </match> <match target="font" > <edit mode="assign" name="antialias" > <bool>true</bool> </edit> </match>


Снимки экрана:

Патченный ftdiff. В центре - с подкрученным фильтром, по сторонам - варианты со стандартным значением фильтра.
Изображение

Изображение

Изображение

Патченный ftview.
Изображение

Варианты полученных шрифтов в kedit.
Изображение

Изображение

Изображение
Изображение


Ссылки по теме:
http://ru.wikibooks.org/wiki/Шрифты_в_Linux
http://antigrain.com/research/font_rasterization/index.html
http://www.grc.com/cleartype.htm
http://www.bel.fi/~alankila/blog/2007/04/2...nts%20suck.html
http://www.lagom.nl/lcd-test/subpixel.php — различные тесты для ЖК-мониторов

ps: Настроить идеальное отображение на одном размере шрифта гораздо легче, чем настроить хорошее отображение на всех размерах. Тут бы помогло задание различных фильтров для разных размеров шрифта (вроде проскакивала информация, что что-то подобное делается в злоОС). Никто не хочет заняться этим вопросом? ;)
И, да, не забываем про шрифты от свисты, для субпиксельного я пока ничего лучше не нашел (dejavu sans condensed правда тоже очень неплох, может еще чего есть... =\ )


Пробуем, делимся впечатлениями. %)


старые патчи для 2.3.7 версии:
freetype-2.3.7-set_lcd_filter_weights-20090125.diff

Код:

--- freetype-2.3.7.original/include/freetype/ftlcdfil.h 2008-06-26 12:59:58.000000000 +0400 +++ freetype-2.3.7.patched/include/freetype/ftlcdfil.h 2008-11-23 22:56:07.000000000 +0300 @@ -155,5 +155,9 @@ FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter ); + FT_EXPORT( FT_Error ) + FT_Library_SetLcdFilterWeights(FT_Library library, + unsigned char *weights); + /* */ --- freetype-2.3.7.original/src/base/ftlcdfil.c 2008-01-18 07:19:35.000000000 +0300 +++ freetype-2.3.7.patched/src/base/ftlcdfil.c 2009-01-25 19:24:10.000000000 +0300 @@ -265,6 +265,12 @@ #endif /* USE_LEGACY */ + FT_EXPORT( FT_Error ) + FT_Library_SetLcdFilterWeights(FT_Library library, + unsigned char *weights) + { + memcpy(library->lcd_weights, weights, 5); + } FT_EXPORT( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, @@ -335,6 +341,16 @@ #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ +FT_EXPORT( FT_Error ) +FT_Library_SetLcdFilterWeights(FT_Library library, + unsigned char *weights) +{ + FT_UNUSED( library ); + FT_UNUSED( weights ); + + return FT_Err_Unimplemented_Feature; +} + FT_EXPORT( FT_Error ) FT_Library_SetLcdFilter( FT_Library library, FT_LcdFilter filter )


ft2demos-2.3.7-ftdiff-filter_weights_tuner-20090125.diff

Код:

--- ft2demos-2.3.7.original/src/ftdiff.c 2008-05-19 01:52:18.000000000 +0400 +++ ft2demos-2.3.7-mypatch/src/ftdiff.c 2008-12-17 20:18:38.000000000 +0300 @@ -148,6 +148,9 @@ FT_LcdFilter lcd_filter; HintMode hint_mode; DisplayMode disp_mode; + int use_custom_lcd_filter; + unsigned char filter_weights[5]; + int fw_index; } ColumnStateRec, *ColumnState; @@ -202,14 +205,19 @@ state->columns[0].use_lcd_filter = 1; state->columns[0].lcd_filter = FT_LCD_FILTER_DEFAULT; state->columns[0].hint_mode = HINT_MODE_BYTECODE; + state->columns[0].use_custom_lcd_filter = 0; + //freetype default filter weights + memcpy(state->columns[0].filter_weights, "\x10\x40\x70\x40\x10", 5); + state->columns[0].fw_index = 2; state->columns[1] = state->columns[0]; state->columns[1].hint_mode = HINT_MODE_AUTOHINT; + state->columns[1].use_custom_lcd_filter = 1; state->columns[2] = state->columns[0]; state->columns[2].hint_mode = HINT_MODE_UNHINTED; - state->col = 2; + state->col = 1; if ( FT_Init_FreeType( &state->library ) != 0 ) panic( "could not initialize FreeType library. Check your code\n" ); @@ -428,6 +436,10 @@ if ( column->use_lcd_filter ) FT_Library_SetLcdFilter( face->glyph->library, column->lcd_filter ); + if (column->use_custom_lcd_filter) + FT_Library_SetLcdFilterWeights(face->glyph->library, column->filter_weights); + /* memcpy((unsigned char*)face->glyph->library->lcd_weights, column->filter_weights, 5); */ + y += state->size->metrics.ascender / 64; line_height = state->size->metrics.height / 64; @@ -573,20 +585,33 @@ if ( !column->use_lcd_filter ) msg = "gray rendering"; + else if (column->use_custom_lcd_filter) + { + msg = ""; + int fwi = column->fw_index; + unsigned char *fw = column->filter_weights; + sprintf(temp, "%s%d%s%s%d%s%s%d%s%s%d%s%s%d%s", + fwi == 0 ? "[" : " ", fw[0], fwi == 0 ? "]" : " ", + fwi == 1 ? "[" : " ", fw[1], fwi == 1 ? "]" : " ", + fwi == 2 ? "[" : " ", fw[2], fwi == 2 ? "]" : " ", + fwi == 3 ? "[" : " ", fw[3], fwi == 3 ? "]" : " ", + fwi == 4 ? "[" : " ", fw[4], fwi == 4 ? "]" : " "); + state->display.disp_text(disp, left, bottom + 15, temp); + } else switch ( column->lcd_filter ) - { - case FT_LCD_FILTER_NONE: - msg = "lcd without filtering"; - break; - case FT_LCD_FILTER_DEFAULT: - msg = "default lcd filter"; - break; - case FT_LCD_FILTER_LIGHT: - msg = "light lcd filter"; - break; - default: - msg = "legacy lcd filter"; - } + { + case FT_LCD_FILTER_NONE: + msg = "lcd without filtering"; + break; + case FT_LCD_FILTER_DEFAULT: + msg = "default lcd filter"; + break; + case FT_LCD_FILTER_LIGHT: + msg = "light lcd filter"; + break; + default: + msg = "legacy lcd filter"; + } state->display.disp_text( disp, left, bottom + 15, msg ); sprintf(temp, "%s / %s", @@ -800,6 +825,9 @@ grWriteln( " h : toggle hinting mode" ); grWriteln( " r : toggle rendering mode" ); grWriteln( " l : change LCD filter type" ); + grWriteln( " [, ] : select filter weight in custom lcd filter mode" ); + grWriteln( " -, +(=) : increase/decrease selected lcd filter weight value"); + grWriteln( " : in custom lcd filter mode"); grWriteln( " Up : increase pointsize by 0.5 unit" ); grWriteln( " Down : decrease pointsize by 0.5 unit" ); grWriteln( " Page Up : increase pointsize by 5 units" ); @@ -852,8 +880,7 @@ { int ret = 0; ColumnState column = &state->columns[state->col]; - - + switch ( event->key ) { case grKeyEsc: @@ -903,8 +930,17 @@ break; case FT_LCD_FILTER_DEFAULT: - column->lcd_filter = FT_LCD_FILTER_LIGHT; - state->message = (char *)"using light LCD filter"; + if (!column->use_custom_lcd_filter) + { + column->use_custom_lcd_filter = 1; + state->message = (char*)"using custom lcd filter"; + } + else + { + column->use_custom_lcd_filter = 0; + column->lcd_filter = FT_LCD_FILTER_LIGHT; + state->message = (char *)"using light LCD filter"; + } break; case FT_LCD_FILTER_LIGHT: @@ -985,6 +1021,35 @@ event_change_size( state, -5. ); break; + case grKEY('['): + if (!column->use_custom_lcd_filter) + break; + column->fw_index -= 1; + if (column->fw_index < 0) + column->fw_index = 4; + break; + + case grKEY(']'): + if (!column->use_custom_lcd_filter) + break; + column->fw_index += 1; + if (column->fw_index > 4) + column->fw_index = 0; + break; + + case grKEY('-'): + if (!column->use_custom_lcd_filter) + break; + column->filter_weights[column->fw_index] -= 1; + break; + + case grKEY('+'): + case grKEY('='): + if (!column->use_custom_lcd_filter) + break; + column->filter_weights[column->fw_index] += 1; + break; + default: break; }
Спасибо сказали:

Аватара пользователя
sspphheerraa
Сообщения: 1375
ОС: Gentoo

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение sspphheerraa »

Sspphheerraa
Спасибо сказали:

Lifter
Сообщения: 7
ОС: GNU/Linux

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение Lifter »

sspphheerraa, тоньше.
Спасибо сказали:

Аватара пользователя
foxnx6110
Сообщения: 82
ОС: Gentoo

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение foxnx6110 »

Собрал ft2demos(у меня, кстати, компиляция пошла только при make X11_PATH=/usr),
повертел фильтр, и пришел к выводу, что для меня больше подходит менее контрастный вид шрифтов, - фильтр (0_34_84_52_16).
Сумма всех значений не равняется 256, я это просто игнорировал. Результат на снимке, в верхней части для сравнения два варианта с разным хинтингом, одназначно трудно сказать, что лучше, но я остановился на нижнем(autohinter). Но "жирные" шрифты выглядят при этом визуально еще жирнее. Чтобы не злоупотреблять "холестирином" добавил в ~/fonts.conf, представленный г-ном Lifter строки, выключающие автохитинг только для bold-шрифтов. Вставить в начало 9-й строки(после '</match>').

Код: Выделить всё

 <match target="font">
         <test name="weight" compare="more">
             <const>medium</const>
         </test>
         <edit name="autohint" mode="assign">
             <bool>false</bool>
         </edit>

Внизу снимка можно посмотреть результат этого.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Я НЕ КРАСНОГЛАЗЫЙ ! И никогда им не стану.
Спасибо сказали:

Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение diesel »

Lifter спасибо, интересно, есть над чем подумать, попробую попробовать +1 в карму ))
Спасибо сказали:

Lifter
Сообщения: 7
ОС: GNU/Linux

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение Lifter »

foxnx6110 писал(а):
14.02.2009 20:36
Результат на снимке, в верхней части для сравнения два варианта с разным хинтингом, одназначно трудно сказать, что лучше, но я остановился на нижнем(autohinter).

А мне больше верхний понравился, у меня выглядит почетче и тоньше. %) Ну тут от монитора и вкуса зависит, у тебя сколько dpi? Я использую autohinter, потому что на свистовских шрифтах native hinter дает какую-то мазню по вертикали, с DejaVu такого точно нет, наверное, с другими тоже. =\
Спасибо сказали:

Аватара пользователя
foxnx6110
Сообщения: 82
ОС: Gentoo

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение foxnx6110 »

Монитор у меня 15' 1024*768, реальный dpi=86, но повсюду в X11 прописано 96. Ну и для ftview и ftdiff я также указывал 96(хотя и 86 проверил - на глаз разница только в размере). Я также вбил и в LCD_LIGHT те же значения, что и для DEFAULT, на всякий случай. Специально проверил вид Вистовых шрифтов(Calibri, Corbel, Cambria, Candara, Constantia) с разным типом хинтинга - не нашел чего то такого, что могло бы бросаться в глаза. Выглядят отлично. Я их, правда, не использую по другой причине. К буквам претензий нет, но цифры ! Пьяная курица, левой лапой, да еще и в понедельник... До сих пор не могу понять этот прикол - зачем нужно было делать разные по высоте и сдвинутые, относительно центра строки по горизонтали цифры.
По-моему, autohint дает более приятный вид шрифтов на малых размерах(Microsoft Sans Serif,7).

Добавлю :
Написал ~/fonts.conf, который задействует autohint на всех размерах шрифтов, кроме от 9 до 11(включительно), при этом autohint полностью отключен для всех bold-шрифтов.
fonts.conf

Код:

<?xml version='1.0'?> <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> <fontconfig> <match target="font" > <edit mode="assign" name="rgba" > <const>rgb</const> </edit> </match> <match target="font" > <edit mode="assign" name="hinting" > <bool>true</bool> </edit> </match> <match target="font" > <edit mode="assign" name="hintstyle" > <const>hintfull</const> </edit> </match> <match target="font" > <edit mode="assign" name="autohint" > <bool>true</bool> </edit> </match> <match target="font"> <test name="weight" compare="more"> <const>medium</const> </test> <edit name="autohint" mode="assign"> <bool>false</bool> </edit> </match> <match target="font" > <edit mode="assign" name="antialias" > <bool>true</bool> </edit> </match> <match target="font" > <test compare="more_eq" name="size" qual="any" > <double>9</double> </test> <test compare="less_eq" name="size" qual="any" > <double>11</double> </test> <edit mode="assign" name="autohint" > <bool>false</bool> </edit> </match> <match target="font" > <test compare="more_eq" name="pixelsize" qual="any" > <double>12</double> </test> <test compare="less_eq" name="pixelsize" qual="any" > <double>15</double> </test> <edit mode="assign" name="autohint" > <bool>false</bool> </edit> </match> </fontconfig>


"И волки сыты, и овцы целы ..."
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Я НЕ КРАСНОГЛАЗЫЙ ! И никогда им не стану.
Спасибо сказали:

Lifter
Сообщения: 7
ОС: GNU/Linux

Re: Шрифты. Тонкая подстройка субпиксельной отрисовки

Сообщение Lifter »

foxnx6110 писал(а):
17.02.2009 11:52
Монитор у меня 15' 1024*768, реальный dpi=86, но повсюду в X11 прописано 96. Ну и для ftview и ftdiff я также указывал 96(хотя и 86 проверил - на глаз разница только в размере).

Значит у нас почти одинаковая картинка должна быть, осталась лишь разница в глазах..%) Эт да, зато от реального дпи сильно зависит (не)восприятие "цветной мазни".
Я также вбил и в LCD_LIGHT те же значения, что и для DEFAULT, на всякий случай.

Вроде бы оно только при hintslight задействуется, при котором, кстати, включается автохинтер даже если у тебя прописан navite или autohinter = false. хе-хе. Там не разберешь сходу настоящую зависимость от условных параметров fontconfig-а. :]

Хых, я сначала подумал, что это баг во freetype с цифрами в шрифтах от висты, вроде ошибки обработки хинтов или что-то вроде того. :D Кстати, в cambria и segoe нормальные цифры. С прыгующими, вероятно, легче читать длинные последовательности цифр, я привык. Теперь даже нравится, тем более, что оно в тырнете только, а так - segoe стоит.

По-моему, autohint дает более приятный вид шрифтов на малых размерах(Microsoft Sans Serif,7).

Ага, на снимке видно. Наверное, из-за бОльшего межсимвольного промежутка с автохинтером, может и мазня более грамотная. ))
Спасибо сказали: