C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 30.09.04 00:24
Оценка: 144 (18)
Тема навеяна краткой заметкой Яна Грифитса:
http://www.interact-sw.co.uk/iangblog/2004/07/22/longhorncleartype
В которой он выразил восхищение алгоритмом ClearType в Longhorn. Кроме того, Дэйв Гибсон подробно исследовал, как работает ClearType вообще:
http://www.grc.com/ctwhat.htm
В методе Дейва, так же как и в ClearType XP анти-алиасинг не используется, он получается за счет втрое большего разрешения по X. Вот Ян Грифитс и был этим фактом недоволен, о чем он так же писал в более ранней заметке.


И вот я думал-подумал и решил, что если взять метод Гибсона и скомбинировать его со сглаженными шрифтами, то как раз и получится Longhorn ClearType. Так оно и есть и я могу с уверенностью утверждать, что используемый мной метод всяко лучше, чем в XP. При этом я не использую ничего, кроме простого C++ и WinAPI.

Замечания.
0. На CRT-мониторах (любых, включая Trinitron) не работает, увы.

1. Дабы не усложнять код, используется R-G-B порядок и соответственно, 24бит TrueColor. Расчитано тоже только на R-G-B порядок цветовых триад в LCD-дисплеях (кто-нибудь видел B-G-R?). Соответственно, приходится приводить буфер к B-G-R, который по непонятным причинам используется в WinPAI. Для работы непосредственно в B-G-R или в 32-битовом пространстве с альфа-каналом, надо модифицировать blend_lcd_span. Это может быть не так-то просто как кажется.

2. Цвет может быть полупрозрачным, то есть поддерживается полноценый альфа-блендинг

3. Нет никакого отсечения, соответственно при выходе за границы — падает. Отсечение — задача тривиальная и не входит в рамки данной заметки.

4. Работает сравнительно тормозно. Это обусловлено во-первых, жуткой тормознутостью GetGlyphOutline(), во-вторых, усреднением знечений (распределение энергии) по методу Стива Гибсона. Если сделать кэширование бит-мапов после prepare_lcd_glyph, то скорость станет порядка 250-300 тысяч мелких символов в секунду, то есть, вполне сравнимой с родным HW-accelerated выводом такста.

5. Полный проект находится здесь: http://antigrain.com/stuff/lcd_font.zip

6. Что получается:



//---------------------------------
// A simple helper class to create font, select object
// and properly destroy it.
class lcd_font
{
public:
    ~lcd_font()
    {
        ::SelectObject(m_hdc, m_old_font);
        ::DeleteObject(m_font);
    }

    lcd_font(HDC hdc, const char* typeface, int height, bool bold=false, bool italic=false) :
        m_hdc(hdc),
        m_font(::CreateFont(height,               // height of font
                            0,                    // average character width
                            0,                    // angle of escapement
                            0,                    // base-line orientation angle
                            bold ? 700 : 400,     // font weight
                            italic,               // italic attribute option
                            FALSE,                // underline attribute option
                            FALSE,                // strikeout attribute option
                            ANSI_CHARSET,         // character set identifier
                            OUT_DEFAULT_PRECIS,   // output precision
                            CLIP_DEFAULT_PRECIS,  // clipping precision
                            ANTIALIASED_QUALITY,  // output quality
                            FF_DONTCARE,          // pitch and family
                            typeface)),           // typeface name
        m_old_font(::SelectObject(m_hdc, m_font))
    {
    }

private:
    HDC     m_hdc;
    HFONT   m_font;
    HGDIOBJ m_old_font;
};


// Possible formats for GetGlyphOutline() and corresponding 
// numbers of levels of gray.
//---------------------------------
struct ggo_gray2 { enum { num_levels = 5,  format = GGO_GRAY2_BITMAP }; };
struct ggo_gray4 { enum { num_levels = 17, format = GGO_GRAY4_BITMAP }; };
struct ggo_gray8 { enum { num_levels = 65, format = GGO_GRAY8_BITMAP }; };


// Sub-pixel energy distribution lookup table.
// See description by Steve Gibson: http://grc.com/cttech.htm
// The class automatically normalizes the coefficients
// in such a way that primary + 2*secondary + 3*tertiary = 1.0
// Also, the input values are in range of 0...NumLevels, output ones
// are 0...255
//---------------------------------
template<class GgoFormat> class lcd_distribution_lut
{
public:
    lcd_distribution_lut(double prim, double second, double tert)
    {
        double norm = (255.0 / (GgoFormat::num_levels - 1)) / (prim + second*2 + tert*2);
        prim   *= norm;
        second *= norm;
        tert   *= norm;
        for(unsigned i = 0; i < GgoFormat::num_levels; i++)
        {
            m_primary[i]   = (unsigned char)floor(prim   * i);
            m_secondary[i] = (unsigned char)floor(second * i);
            m_tertiary[i]  = (unsigned char)floor(tert   * i);
        }
    }

    unsigned primary(unsigned v)   const { return m_primary[v];   }
    unsigned secondary(unsigned v) const { return m_secondary[v]; }
    unsigned tertiary(unsigned v)  const { return m_tertiary[v];  }

    static unsigned ggo_format()
    {
        return GgoFormat::format;
    }

private:
    unsigned char m_primary[GgoFormat::num_levels];
    unsigned char m_secondary[GgoFormat::num_levels];
    unsigned char m_tertiary[GgoFormat::num_levels];
};



// This function prepares the alpha-channel information 
// for the glyph averaging the values in accordance with 
// the method suggested by Steve Gibson. The function
// extends the width by 4 extra pixels, 2 at the beginning 
// and 2 at the end. Also, it doesn't align the new width 
// to 4 bytes, that is, the output gm.gmBlackBoxX is the 
// actual width of the array.
//---------------------------------
template<class LutType>
void prepare_lcd_glyph(const LutType& lut, 
                       const unsigned char* gbuf1, 
                       const GLYPHMETRICS& gm, 
                       unsigned char* gbuf2, 
                       GLYPHMETRICS* gm2)
{
    unsigned src_stride = (gm.gmBlackBoxX + 3) / 4 * 4;
    unsigned dst_width  = src_stride + 4;
    memset(gbuf2, 0, dst_width * gm.gmBlackBoxY);

    for(unsigned y = 0; y < gm.gmBlackBoxY; ++y)
    {
        const unsigned char* src_ptr = gbuf1 + src_stride * y;
        unsigned char* dst_ptr = gbuf2 + dst_width * y;
        unsigned x;
        for(x = 0; x < gm.gmBlackBoxX; ++x)
        {
            unsigned v = *src_ptr++;
            dst_ptr[0] += lut.tertiary(v);
            dst_ptr[1] += lut.secondary(v);
            dst_ptr[2] += lut.primary(v);
            dst_ptr[3] += lut.secondary(v);
            dst_ptr[4] += lut.tertiary(v);
            ++dst_ptr;
        }
    }
    gm2->gmBlackBoxX = dst_width;
}


// Color struct
//---------------------------------
struct rgba
{
    rgba() : r(0), g(0), b(0), a(255) {}
    rgba(unsigned char r_, unsigned char g_, unsigned char b_, unsigned char a_=255) : 
        r(r_), g(g_), b(b_), a(a_) {}
    unsigned char r,g,b,a;
};



// Blend one span into the R-G-B 24 bit frame buffer
// For the B-G-R byte order or for 32-bit buffers modify
// this function accordingly. The general idea is 'span' 
// contains alpha values for individual color channels in the 
// R-G-B order, so, for the B-G-R order you will have to 
// choose values from the 'span' array differently
//---------------------------------
void blend_lcd_span(int x, 
                    int y, 
                    const unsigned char* span, 
                    int width, 
                    const rgba& color, 
                    unsigned char* rgb24_buf, 
                    unsigned rgb24_stride)
{
    unsigned char* p = rgb24_buf + rgb24_stride * y + x;
    unsigned char rgb[3] = { color.r, color.g, color.b };
    int i = x % 3;
    do
    {
        int a0 = int(*span++) * color.a;
        *p++ = (unsigned char)((((rgb[i++] - *p) * a0) + (*p << 16)) >> 16);
        if(i > 2) i = 0;
    }
    while(--width);
}



// Blend one rectangular glyph
//---------------------------------
void blend_lcd_glyph(const unsigned char* gbuf, 
                     int x, 
                     int y, 
                     const rgba& color,
                     const GLYPHMETRICS& gm, 
                     unsigned char* rgb24_buf, 
                     unsigned rgb24_stride)
{

    for(unsigned i = 0; i < gm.gmBlackBoxY; i++)
    {
        blend_lcd_span(x + gm.gmptGlyphOrigin.x, 
                       y + gm.gmptGlyphOrigin.y - i, 
                       gbuf + gm.gmBlackBoxX * i, 
                       gm.gmBlackBoxX, 
                       color, 
                       rgb24_buf, 
                       rgb24_stride);
    }
}



// Draw a text string in the frame buffer
//---------------------------------
template<class LutType, class CharT>
void draw_lcd_text(HDC hdc, 
                   const LutType& lut,
                   int x, 
                   int y, 
                   const rgba& color, 
                   const CharT* str, 
                   unsigned char* rgb24, 
                   unsigned stride)
{
    // Create an affine matrix with 3x horizontal scaling.
    // 3x means that we interpret each pixel in the resulting glyph
    // in such a way that it corresponds to the sublixel 
    // (red, green, or blue), but not to the whole pixel.
    //----------------------------------
    MAT2 scale3h;
    memset(&scale3h, 0, sizeof(MAT2));
    scale3h.eM11.value = 3;
    scale3h.eM22.value = 1;

    // Allocate buffers for glyphs
    // In reality use some smarter strategy to detect
    // the size of the buffer
    unsigned gbuf_size = 16*1024; 
    unsigned char* gbuf1 = new unsigned char [gbuf_size];
    unsigned char* gbuf2 = new unsigned char [gbuf_size];

    while(*str)
    {
        GLYPHMETRICS gm;
        int total_size = GetGlyphOutline(hdc,
                                         *str,
                                         lut.ggo_format(),
                                         &gm,
                                         gbuf_size,
                                         (void*)gbuf1,
                                         &scale3h);
        if(total_size >= 0)
        {
            prepare_lcd_glyph(lut, gbuf1, gm, gbuf2, &gm);
            blend_lcd_glyph(gbuf2, x, y, color, gm, rgb24, stride);
        }
        else
        {
            // GetGlyphOutline() fails when being called for
            // GGO_GRAY8_BITMAP and white space (stupid Microsoft).
            // It doesn't even initialize the glyph metrics
            // structure. So, we have to query the metrics
            // separately (basically we need gmCellIncX).
            total_size = GetGlyphOutline(hdc,
                                         *str,
                                         GGO_METRICS,
                                         &gm,
                                         gbuf_size,
                                         (void*)gbuf1,
                                         &scale3h);
        }

        x += gm.gmCellIncX;
        ++str;
    }
    delete [] gbuf2;
    delete [] gbuf1;
}



// Swap Blue and Red, that is convert RGB->BGR or BGR->RGB
//---------------------------------
void swap_rb(unsigned char* buf, unsigned width, unsigned height, unsigned stride)
{
    unsigned x, y;
    for(y = 0; y < height; ++y)
    {
        unsigned char* p = buf + stride * y;
        for(x = 0; x < width; ++x)
        {
            unsigned char v = p[0];
            p[0] = p[2];
            p[2] = v;
            p += 3;
        }
    }
}



Далее — пример обработчика WM_PAINT:


        case WM_PAINT:
            {
                hdc = BeginPaint(hWnd, &ps);
                RECT rt;
                GetClientRect(hWnd, &rt);

                int width = rt.right - rt.left;
                int height = rt.bottom - rt.top;

                //Create compatible DC and a bitmap to render the image 
                //--------------------------------------
                BITMAPINFO bmp_info; 
                bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
                bmp_info.bmiHeader.biWidth = width; 
                bmp_info.bmiHeader.biHeight = height; 
                bmp_info.bmiHeader.biPlanes = 1; 
                bmp_info.bmiHeader.biBitCount = 24;
                bmp_info.bmiHeader.biCompression = BI_RGB; 
                bmp_info.bmiHeader.biSizeImage = 0; 
                bmp_info.bmiHeader.biXPelsPerMeter = 0; 
                bmp_info.bmiHeader.biYPelsPerMeter = 0; 
                bmp_info.bmiHeader.biClrUsed = 0; 
                bmp_info.bmiHeader.biClrImportant = 0; 

                HDC mem_dc = ::CreateCompatibleDC(hdc); 

                void* buf = 0; 

                HBITMAP bmp = ::CreateDIBSection( 
                    mem_dc, 
                    &bmp_info, 
                    DIB_RGB_COLORS, 
                    &buf, 
                    0, 
                    0 
                ); 

                HBITMAP temp = (HBITMAP)::SelectObject(mem_dc, bmp);

                // Calculate image stride and size 
                //---------------------------------
                unsigned char* rgb24  = (unsigned char*)buf;
                unsigned rgb24_stride = (width * 3 + 3) / 4 * 4;
                unsigned rgb24_size   = height * rgb24_stride;

                // Clear the image
                //---------------------------------
                memset(rgb24, 255, rgb24_size);


                // Create the energy distribution lookup table.
                // See description by Steve Gibson: http://grc.com/cttech.htm
                // The class automatically normalizes the coefficients
                // in such a way that primary + 2*secondary + 3*tertiary = 1.0
                // Also, the input values are in range of 0...64, output ones
                // are 0...255.
                // 
                // Try to play with different coefficients for the primary,
                // secondary, and tertiary distribution weights.
                // Steve Gibson recommends 1/3, 2/9, and 1/9, but it produces 
                // too blur edges. It's better to increase the weight of the 
                // primary and secondary pixel, then the text looks much crisper 
                // with inconsiderably increased "color fringing".
                //---------------------------------
                //lcd_distribution_lut<ggo_gray8> lut(1.0/3.0, 2.0/9.0, 1.0/9.0);
                lcd_distribution_lut<ggo_gray8> lut(0.5, 0.25, 0.125);


                // Use a separate block to make sure the font will be created, 
                // used with current DC and destroyed correctly (we need to 
                // SelectObject(prev_font) before destroying)
                //---------------------------------
                {
                    // Draw text
                    //---------------------------------
                    lcd_font fnt(hdc, "Arial", -20, false, true);
                    draw_lcd_text(hdc, 
                                  lut, 
                                  50 * 3,    // X-positioning is also sub-pixel!
                                  100, 
                                  rgba(0,30,40, 230),
                                  "Hello World! Welcome to the perfectly LCD-optimized text rendering!", 
                                  rgb24, rgb24_stride);
                }


                {
                    // Draw "Copyright"
                    //---------------------------------
                    lcd_font fnt(hdc, "Arial", -12, false, false);
                    draw_lcd_text(hdc, lut, 
                                  120 * 3,  // X-positioning is also sub-pixel!
                                  80, 
                                  rgba(50,20,0, 220),
                                  L"\xA9 Maxim Shemanarev http://antigrain.com", 
                                  rgb24, rgb24_stride);
                }


                {
                    // Draw the big "o"
                    //---------------------------------
                    lcd_font fnt(hdc, "Arial", -100, false, false);
                    draw_lcd_text(hdc, lut, 
                                  50 * 3,    // X-positioning is also sub-pixel!
                                  10, 
                                  rgba(0,0,0),
                                  "O", 
                                  rgb24, rgb24_stride);
                }


                // The drawing method assumes the R-G-B byte order,
                // so that we have to change it to the native Windows one 
                // (B-G-R) to obtain the correct result.
                //-------------------------------------------------
                swap_rb(rgb24, width, height, rgb24_stride);


                // Display the image. If the image is B-G-R-A (32-bits per pixel)
                // one can use AlphaBlend instead of BitBlt. In case of AlphaBlend
                // one also should clear the image with zero alpha, i.e. rgba8(0,0,0,0)
                //-------------------------------------------------
                ::BitBlt(
                  hdc,  
                  rt.left,      
                  rt.top,      
                  width,  
                  height, 
                  mem_dc,
                  0,
                  0,     
                  SRCCOPY
                );

                // Free resources 
                ::SelectObject(mem_dc, temp); 
                ::DeleteObject(bmp); 
                ::DeleteObject(mem_dc);

                EndPaint(hWnd, &ps);
            }
            break;


Необходимое примечание:
ClearType is a trademark of Microsoft Corporation, Redmond, WA
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: C++/WinAPI: ClearType как он есть
От: alexeiz  
Дата: 30.09.04 05:21
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>И вот я думал-подумал и решил, что если взять метод Гибсона и скомбинировать его со сглаженными шрифтами, то как раз и получится Longhorn ClearType. Так оно и есть и я могу с уверенностью утверждать, что используемый мной метод всяко лучше, чем в XP.


Может быть для тебя это и называется лучше, но на мой вкус уж точно хуже. Для шрифтов большого размера cleartype или anti-aliasing не имеет большого значения: они и так выглядят гладко. Но для маленьких шрифтов разница ощутимая.

Сравним твой rendering с cleartype-ом:



Твой rendering выглядит сероватым. Тогда как cleartype — четок, а твой — расплывчит.

Тот алгоритм, который ты используешь наверняка сходен с тем, что применяется в Gnome для lcd anti-aliasing. Он тоже уступает cleartype'у. Даже adobe'овский cooltype хуже, чем cleartype.
Re[2]: C++/WinAPI: ClearType как он есть
От: c-smile Канада http://terrainformatica.com
Дата: 30.09.04 05:45
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Твой rendering выглядит сероватым. Тогда как cleartype — четок, а твой — расплывчит.


Алекс ну нельзя ж так...

см. rgba(50,20,0, 220)
Re[3]: C++/WinAPI: ClearType как он есть
От: alexeiz  
Дата: 30.09.04 06:21
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, alexeiz, Вы писали:


A>>Твой rendering выглядит сероватым. Тогда как cleartype — четок, а твой — расплывчит.


CS>Алекс ну нельзя ж так...


CS>см. rgba(50,20,0, 220)


Т.е. ты хочешь сказать, что это так задумывалось? А слабо сделать так же четко, как cleartype?

Дело в том, что cleartype — это не просто разбиение пикселя на три с получением за счет этого трехкратного горизонтального разрешения. Там целая теория о том, как отобразить непрерывные символы на дискретное пространство монитора, с волновым представлением изображения, преобразованиями фурье и т.д. Одним интересным следствием этой теории является то, что наиболее четко cleartype можно отобразить на немного сером фоне. Почему? Потому, что на сером фоне можно представить не только положительную амплитуду (более черный цвет), но и отрицательную (более белый).

На счет маленьких шрифтов. Они специальным образом изменены, чтобы выглядеть лучше в cleartype'е. Поэтому если взять default 10pt шрифт и пытаться его сгладить, то такого же результата не добиться.
Re[4]: C++/WinAPI: ClearType как он есть
От: c-smile Канада http://terrainformatica.com
Дата: 30.09.04 18:52
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>>>Твой rendering выглядит сероватым. Тогда как cleartype — четок, а твой — расплывчит.


CS>>Алекс ну нельзя ж так...


CS>>см. rgba(50,20,0, 220)


A>Т.е. ты хочешь сказать, что это так задумывалось? А слабо сделать так же четко, как cleartype?


Я хочу сказать что твое замечание "Твой rendering выглядит сероватым" относится к двум образцам которые мало того что различаются цветом но и шрифтом к тому же.
Re[5]: C++/WinAPI: ClearType как он есть
От: alexeiz  
Дата: 30.09.04 19:58
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, alexeiz, Вы писали:


A>>>>Твой rendering выглядит сероватым. Тогда как cleartype — четок, а твой — расплывчит.


CS>>>Алекс ну нельзя ж так...


CS>>>см. rgba(50,20,0, 220)


A>>Т.е. ты хочешь сказать, что это так задумывалось? А слабо сделать так же четко, как cleartype?


CS>Я хочу сказать что твое замечание "Твой rendering выглядит сероватым" относится к двум образцам которые мало того что различаются цветом но и шрифтом к тому же.


Ну если человек хотел показать, что его алгоритм лучше, чем cleartype, то я думал, он наилучший случай выберет. Как-то странно, что он серый цвет взял, а потом сказал: "вот это есть лучше, чем cleartype." А шрифт здесь большого значения не имеет. Он очень похож, и этого достаточно для сравнительных целей.
Re[4]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 30.09.04 20:42
Оценка: 11 (2)
Здравствуйте, alexeiz, Вы писали:

A>Т.е. ты хочешь сказать, что это так задумывалось? А слабо сделать так же четко, как cleartype?


Так достаточно четко?


A>Дело в том, что cleartype — это не просто разбиение пикселя на три с получением за счет этого трехкратного горизонтального разрешения. Там целая теория о том, как отобразить непрерывные символы на дискретное пространство монитора, с волновым представлением изображения, преобразованиями фурье и т.д.


Да, это они любят... Туману напустить.

A>Одним интересным следствием этой теории является то, что наиболее четко cleartype можно отобразить на немного сером фоне. Почему? Потому, что на сером фоне можно представить не только положительную амплитуду (более черный цвет), но и отрицательную (более белый).


Никто не мешает применить фильтры более высоких порядков. И наилучший из них — это классисеский Ланкош.
Но на практике это не так уж и важно. Для высокой четкости гораздо важее хинтинг.

A>На счет маленьких шрифтов. Они специальным образом изменены, чтобы выглядеть лучше в cleartype'е. Поэтому если взять default 10pt шрифт и пытаться его сгладить, то такого же результата не добиться.


Вот. Они модифицировали еще и вычисление хинтов с учетом втрое большего разрешения по горизонтали. Но толку от этого не много, поскольку их шрифты будут красивыми, а чьи-то другие — кривоватыми. Какой от этих модификаций прок?

A>Тот алгоритм, который ты используешь наверняка сходен с тем, что применяется в Gnome для lcd anti-aliasing. Он тоже уступает cleartype'у. Даже adobe'овский cooltype хуже, чем cleartype.


Не могу согласиться. Дело в том, что MS любит заниматься профанацией и покупать людей на внешней красивости, скрывая внутреннюю кривизну. Не спорю, с точки зрения бизнеса и выкачивания прибыли это "умно и мудро". Что они делают. Они добиваются наилучшего визуального качества для одного конкретного случая, а именно, для нескольких наиболее употребимых кеглей. Как только дело касается масштабирования и хорошо согласованного внешнего вида на экране и на печати, то здесь Адоба кроет MS как бык овцу. Почему издатели не любят TrueType а предпочитают Type1? Именно из за более "когерентного" поведения.
Та же самая ситуация наблюдается и с ClearType, который яко-бы лучше. В общем, я не спорю, MS ClearType выглядит более четким, чем мой. Во-первых, это потому, что в MS нет анти-алиасинга перед преобразованием (кстати, в Longhorn будет, вот и посмотрим), во-вторых, MS ClearType никак не заточен для субпиксельного позиционивания. Там все вертикальные линии выравниваются строго на границу целых пикселов. Как только ты попробуешь смасштабировать, вот здесь оно и вылезет наружу. Как, например, сделать такое:

И возможно ли это вообще с MS ClearType? Сильно сомневаюсь.

Я поигрался с разними весами распределения энергии и могу сказать, что вполне можно добиться такой же хорошей четкости. Ожнако, как только становится актуальным субпиксельное позиционирование, при высокой четкости получаем вот это:

Ууу, какое все красиво-разноцветное...
Хотя отобразить более-менее корректно все-таки можно:

Но значения коэффициентов фильтра при этом таковы, что текст выглядит чуть более размытым при масштабе 1:1.

Природу здесь не обманешь ни с помошью Фурье, ни даже с помошью Клода Шеннона
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[6]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 30.09.04 21:10
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Ну если человек хотел показать, что его алгоритм лучше, чем cleartype, то я думал, он наилучший случай выберет.


Кто сказал, что "наиболее контрастный" означает "наилучший"? Это, знаете ли, всего-лишь ваше мнение
К тому же, в качестве доказательства концепции, я постарался нарисовать текст разными цветами и даже с полу-прозрачностью. Здесь показателем является не только четкость, но сохранность визуально воспринимаемого цвета.

A>Как-то странно, что он серый цвет взял, а потом сказал: "вот это есть лучше, чем cleartype." А шрифт здесь большого значения не имеет. Он очень похож, и этого достаточно для сравнительных целей.


Пожалуйста, еще один вариант:


Не могу согласиться, что "шрифт здесь большого значения не имеет". Очень даже имеет. MS шрифты отличаются корявостью, по сравнению с Адобовскими — спросите любого издателя. Да что там издателя — меня спросите До сих пор в системе нет ни одного нормально выглядящего monospaced шрифта для программирования. Вроде бы каждая буква по отдельности смотрится нормально, а общее впечатление — отвратное. Так и пришлось свои собственные делать...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 30.09.04 22:22
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Может быть для тебя это и называется лучше, но на мой вкус уж точно хуже. Для шрифтов большого размера cleartype или anti-aliasing не имеет большого значения: они и так выглядят гладко. Но для маленьких шрифтов разница ощутимая.


A>Сравним твой rendering с cleartype-ом:


. . .

Сравнивать увеличенные изображения совершенно бессмыссленно.
Я восстановил твой пример в натуральную величину:

И могу утверждать, что это выглядит очень плохо. Символы слишком "цветные", особенно по краям "M", "m", "h" и "r". Цветные ореолы просто бросаются в глаза. Я бы предпочел простой битмаповый текст в таком случае. Да и потом, почему промежутки между "Sh" и "ma" такие большие? Они что не знают что такое "кернинг"?
Итак, сравним:


Кстати, прошу обратить внимание, что мой вариант по контрастности выглядит примерно как простой несглаженный текст. Твой вариант выглядит субъективно "жирнее", и при этом — с цветовыми ореолами.


McSeem
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: C++/WinAPI: ClearType как он есть
От: alexeiz  
Дата: 30.09.04 23:43
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, alexeiz, Вы писали:


A>>Может быть для тебя это и называется лучше, но на мой вкус уж точно хуже. Для шрифтов большого размера cleartype или anti-aliasing не имеет большого значения: они и так выглядят гладко. Но для маленьких шрифтов разница ощутимая.


A>>Сравним твой rendering с cleartype-ом:


MS>. . .


MS>Сравнивать увеличенные изображения совершенно бессмыссленно.

MS>Я восстановил твой пример в натуральную величину:
MS>
MS>И могу утверждать, что это выглядит очень плохо.

Ну, получается, на вкус и цвет товарищей нет.

>Символы слишком "цветные", особенно по краям "M", "m", "h" и "r". Цветные ореолы просто бросаются в глаза.


Я не вижу никаких ореолов. Причем как на LCD (1400x1050) так и на CRT (1280x960). Даже если в упор смотреть (если совсем в упор, то что-то там все-таки видно, только непонятно, что).

>Я бы предпочел простой битмаповый текст в таком случае. Да и потом, почему промежутки между "Sh" и "ma" такие большие? Они что не знают что такое "кернинг"?


Я так думаю, что это тот самый эффект, когда символы насильно выравниваются по границе пикселя. Если подряд несколько раз написать, то в некоторых случаях kerning хороший, в некоторых плохой между причем в разных местах.

MS>Итак, сравним:

MS>
MS>
MS>Кстати, прошу обратить внимание, что мой вариант по контрастности выглядит примерно как простой несглаженный текст. Твой вариант выглядит субъективно "жирнее", и при этом — с цветовыми ореолами.

Ты привык к не cleartype тексту, как я вижу. Поэтому cleartype для тебя жирнее. А ореолы, вероятно, от слабого разрешения монитора.
Re[4]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 01.10.04 00:04
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Я не вижу никаких ореолов. Причем как на LCD (1400x1050) так и на CRT (1280x960). Даже если в упор смотреть (если совсем в упор, то что-то там все-таки видно, только непонятно, что).


Смотрел на 21" 1600x1200 и на 19" 1280x1024. Очень "цветно". На CRT 19" 1280x1024 не заметно, но это и не имеет значения. На лаптопе Dell Inspiron, 15" 1600x1200 тоже почти не заметно, видимо MS ориентируется в основном на лаптопы. Но субъективно, мой вариант выглядит гораздо мягче при сохранении хорошей контрастности и четкости.
Вот здесь тоже можно скачать и порулить: http://www.grc.com/freeandclear.htm
Нетрудно заметить, что простыми манипуляциями можно получить MS вариант или даже лучше. Откуда следует, что все эти разговоры о "целой теории" не более, чем запудривание мозгов

A>Ты привык к не cleartype тексту, как я вижу. Поэтому cleartype для тебя жирнее. А ореолы, вероятно, от слабого разрешения монитора.


Есть такое дело Так уж сложилось, что везде, где у меня LCD, стоит Win2000. А единственный XP работает с CRT...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[7]: C++/WinAPI: ClearType как он есть
От: Andir Россия
Дата: 01.10.04 01:30
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>До сих пор в системе нет ни одного нормально выглядящего monospaced шрифта для программирования. Вроде бы каждая буква по отдельности смотрится нормально, а общее впечатление — отвратное. Так и пришлось свои собственные делать...

[skip img]

Хмм. А ещё варианты есть? Где можно посмотреть и попробовать?

С Уважением, Andir!
Re[8]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 01.10.04 02:00
Оценка: 26 (3)
Здравствуйте, Andir, Вы писали:

A>Хмм. А ещё варианты есть? Где можно посмотреть и попробовать?


http://antigrain.com/stuff/mcs_fon.zip

Но предупреждаю, что фонты не очень корректны с точки зрения параметров. И русских букв нету. Просто пользовался каким-то кривым пиксельным редактором и довел до кондиции, удовлетворяющей лично меня Если кто-нибудь возьмется доделать как следует, будет замечательно.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[5]: C++/WinAPI: ClearType как он есть
От: alexeiz  
Дата: 01.10.04 06:03
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, alexeiz, Вы писали:


A>>Я не вижу никаких ореолов. Причем как на LCD (1400x1050) так и на CRT (1280x960). Даже если в упор смотреть (если совсем в упор, то что-то там все-таки видно, только непонятно, что).


MS>Смотрел на 21" 1600x1200 и на 19" 1280x1024. Очень "цветно". На CRT 19" 1280x1024 не заметно, но это и не имеет значения.


По-моему, как раз имеет. Не имеет значения, каким образом ты нарисуешь текст, главное, чтобы пользователям это понравилось. Поэтому, если пользователь не заметит ореолов, то о них можно и не беспокоиться. Да, кстати, не нужно обращать внимание, как это выглядет на CRT. Cleartype задумывался для LCD.

>На лаптопе Dell Inspiron, 15" 1600x1200 тоже почти не заметно, видимо MS ориентируется в основном на лаптопы. Но субъективно, мой вариант выглядит гораздо мягче при сохранении хорошей контрастности и четкости.


Верно, субъективно. Для меня твой вариант выглядит излишне серо и расплывчато.

MS>Вот здесь тоже можно скачать и порулить: http://www.grc.com/freeandclear.htm

MS>Нетрудно заметить, что простыми манипуляциями можно получить MS вариант или даже лучше.

А ты не пробовал подстроить cleartype? Не LCD все мониторы одинаковы. Поэтому Microsoft и предлагает возможность вариации параметров cleartype. Я не удивлюсь, если поварьировав эти параметры можно добиться еще более приятного изображения шрифтов в cleartype'е.

> Откуда следует, что все эти разговоры о "целой теории" не более, чем запудривание мозгов


Тем не менее, cleartype запатентован, значит он как минимум нетривиален.

A>>Ты привык к не cleartype тексту, как я вижу. Поэтому cleartype для тебя жирнее. А ореолы, вероятно, от слабого разрешения монитора.


MS>Есть такое дело Так уж сложилось, что везде, где у меня LCD, стоит Win2000. А единственный XP работает с CRT...
Re[6]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 01.10.04 13:23
Оценка:
Здравствуйте, alexeiz, Вы писали:

MS>>Смотрел на 21" 1600x1200 и на 19" 1280x1024. Очень "цветно". На CRT 19" 1280x1024 не заметно, но это и не имеет значения.


A>По-моему, как раз имеет. Не имеет значения, каким образом ты нарисуешь текст, главное, чтобы пользователям это понравилось. Поэтому, если пользователь не заметит ореолов, то о них можно и не беспокоиться. Да, кстати, не нужно обращать внимание, как это выглядет на CRT. Cleartype задумывался для LCD.


Еще раз. На CRT не имеет особого значения, как выглядит Cleartype, есть там ореолы или нет. Лично я, например, не могу смотреть без слез на CRT на Cleartype (любой). Так что CRT вообще не имеет значения.

>> Откуда следует, что все эти разговоры о "целой теории" не более, чем запудривание мозгов


A>Тем не менее, cleartype запатентован, значит он как минимум нетривиален.


Ну разумеется. В патентных бюро сидят люди, которым тоже очень просто запудрить мозги. Была бы их воля, они бы и процесс совокупления запатентовали...

A>А ты не пробовал подстроить cleartype? Не LCD все мониторы одинаковы. Поэтому Microsoft и предлагает возможность вариации параметров cleartype. Я не удивлюсь, если поварьировав эти параметры можно добиться еще более приятного изображения шрифтов в cleartype'е.


А это где делается? Где-то в глубине души? Ничего кроме вульгарного выбора из 6 вариантов в онлайне на сайте MS не нашел...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: C++/WinAPI: ClearType как он есть
От: korzhik Россия  
Дата: 23.11.06 07:54
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>И вот я думал-подумал и решил, что если взять метод Гибсона и скомбинировать его со сглаженными шрифтами, то как раз и получится Longhorn ClearType.


Максим, в твоей статье byte.com &mdash; Inside ClearType in Windows Longhorn ты пишешь:

It would be pretty interesting to use this idea for general vector graphic
rendering. I have my own 2D rendering progect called Anti-Grain Geometry and I
will try to incorporate this technique there.


Вопрос в следующем: использовал ли ты описанную технику для general vector graphic
rendering. И если да, то какие результаты?
Re[2]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 27.11.06 18:03
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Вопрос в следующем: использовал ли ты описанную технику для general vector graphic

K>rendering. И если да, то какие результаты?

Пробовал. В общем и целом работает. Проблема в рутине — там надо сделать для всех этих RGB-BGR на мониторе и в памяти. А так же для вертикального расположения. Да плюс еще трансформация изображений. В общем, по объему получается примерно как еще один AGG.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: C++/WinAPI: ClearType как он есть
От: zz-sergant Россия https://bitbucket.org/zzsergant/hgsccpackage/wiki/Home
Дата: 05.02.07 17:52
Оценка:
Здравствуйте, McSeem2, Вы писали:

Спасибо за инфу.
Наткнулся на небольшое несоответствие в тексте, пока читал:

MS>// The class automatically normalizes the coefficients
MS>// in such a way that primary + 2*secondary + 3*tertiary = 1.0


MS>    lcd_distribution_lut(double prim, double second, double tert)
MS>    {
MS>        double norm = (255.0 / (GgoFormat::num_levels - 1)) / (prim + second*2 + tert*2);
MS>        prim   *= norm;
MS>        second *= norm;
MS>        tert   *= norm;


По идее для tert должен быть коэффициент 3.
Или это по каким-то соображениям изменено ?
-- team zz
Re[2]: C++/WinAPI: ClearType как он есть
От: McSeem2 США http://www.antigrain.com
Дата: 14.02.07 18:40
Оценка:
Здравствуйте, zz-sergant, Вы писали:

MS>>// The class automatically normalizes the coefficients
MS>>// in such a way that primary + 2*secondary + 3*tertiary = 1.0
ZS>


MS>>    lcd_distribution_lut(double prim, double second, double tert)
MS>>    {
MS>>        double norm = (255.0 / (GgoFormat::num_levels - 1)) / (prim + second*2 + tert*2);
MS>>        prim   *= norm;
MS>>        second *= norm;
MS>>        tert   *= norm;
ZS>


ZS>По идее для tert должен быть коэффициент 3.

ZS>Или это по каким-то соображениям изменено ?

Да, это в комментарии ошибка. Должно быть 1,2,2.
// in such a way that primary + 2*secondary + 2*tertiary = 1.0

Ну то есть:
      ** 
   ** ** **
** ** ** ** **
 3  2  1  2  3

И вторичных и третичных коэффициентов — по две штуки. Первичного — один штук.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.