Tuesday, February 19, 2008

Шрифты

Наткнулся на очень интересную статью Максима Шемарёва, автора замечательной библиотеки двухмерной растеризации antigrain.

В ней автор раскрывает вопросы различия субпиксельной растеризации шрифтов у MS, Apple и под линуксом.

Выводы неутешительные.
MS использует очень грубый метод растеризации. Они отказываются от субпиксельной точности и с помощью агрессивного хинтинга вбивают символы в жёсткие границы пикселей. В результате шрифты очень чёткие, но эта чёткость даётся ценой отказа от масштабируемости. В результате все приложения под MS хорошо выглядят лишь при одном DPI - 96. Если у нас монитор имеет больший DPI, например 300. То мы не сможем смасштабировать весь интерфейс под него и придётся ломать глаза на очень маленьких элементах интерфейса и шрифтах.

Но так как большинство пользовательских приложений в мире написано под винды и не масштабируется, то у производителей железа просто нет мотивации выпускать high-DPI мониторы. А у нас нет шансов когда-либо иметь возможность читать текст на мониторе с качеством изображения сопоставимым печатному.

У Apple дела обстоят получше. У них есть субпиксельная точность. Поэтому шрифты обладают масштабируются. Но они излишне размываются, что даёт некий дискомфорт.

Под линуксом шрифты выглядят ужасно. Это не секрет. Во всём виноват опять же хинтинг. Причём проприетарный хинтинг основанный на TT байтовом интерпретаторе.
Но библиотека freetype позволяет достичь качественного и корректного рендеринга шрифтов, даже без использования патентованных технологий. Как это сделать, описывается в статье.

Хотелось бы всё же, что бы MS встали на путь истинный и начали бы поддерживать нормальную масштабируемость шрифтов и элементов GUI. Но в висте пока этого нет
Если пипл хавает помои, то зачем его кормить деликатесами? Стандартный подход монополиста.

Tuesday, February 12, 2008

MotionX приготовление к релизу.

Вообщем написание библиотеки MotionX на текущий момент закончено. Проект на sf.net зарегистрирован. В ближайшие выходные буду комментировать интерфейсы в формате doxygen и генерировать документацию. Настрою системы сборки, к текущей Scons добавлю CMake. Проведу серию тестов, что бы выявить стабильность системы, утечки памяти и прочие ошибки. И если всё будет благополучно, то выложу первый релиз на sf.net.

Кстати, оказалось, что xmmintrin.h это не только MS-specific, оно есть и под GCC на x86 платформе. А значит и под линуксом библиотека сможет использовать SSE.

Я вчера запустил анимацию 50 персонажей, с 50-ти костями на каждом. С SSE фпс было в районе 700, а без SSE - 30.
То есть SSE даёт, в моём случае, более чем двадцати кратное увеличение производительности! Я сам такого не ожидал.
Так что польза от этой технологии иногда может быть весьма ощутимой.
Хотя отключить применение SSE всегда можно флагами компиляции.

Sunday, February 03, 2008

рефакторинг в motionx

Продолжаю делать мощный рефакторинг в библиотеке MotionX. Сегоня сделал inplace загрузку анимаций. Получилось неплохо, особенно если сравнить со старым вариантом.

Было:

template<>
    motionx::FrameSetCPtr   Create<motionx::FrameSet>(const std::string& file)
    {
        motionx::FrameSetPtr    anim(new motionx::FrameSet);
        std::ifstream   in;
        in.open(file.c_str(), std::ios_base::in | std::ios_base::binary);

        if (io::get<int>(in) != anim_file_magic_number)
            throw   motionx::bad_resource("Wrong file type.", file);
        if (io::get<int>(in) != anim_file_version)
            throw   motionx::bad_resource("Wrong file version.", file);

        int frames_count = io::get<int>(in);
        int frame_size   = io::get<int>(in);

        for (int i = 0; i < frames_count; ++i)
        {
            float   time = io::get<float>(in);
            motionx::Frame  frame;
            frame.resize(frame_size);
            frame.Pivot = io::get<mtl::rigid_tm>(in);
            std::generate(frame.begin(), frame.end(), boost::bind(io::get<mtl::rigid_tm>, boost::ref(in)));
            anim->AddFrame(frame, time);
        }

        return  anim;
    }Syhi-подсветка кода


Стало:
Animation*  LoadBinaryAnimation(MotionXLib* lib, const char* filename)
    {           
        IFileSystem*   fs = lib->FileSystem();
        AutoFileHandle f = (fs->Open(filename, "r+b"), fs);
        if (!f)
        {
            OnError(IOError(filename));
            return;
        }

        size_t  fileSize = fs->Size(f);
        int magicNumber = 0;
        int version     = 0;
        fs->Read(f, (char*)&magicNumber, 4);
        fs->Read(f, (char*)&version, 4);

        if (magicNumber != anim_file_magic_number || version != anim_file_version)
        {
            OnError(BadResource(filename));
            return;
        }

        InplaceAnimation* animData = AllocateMemory(fileSize - 8);
        fs->Read(f, animData, fileSize - 8);
        return new Animation(animData);
    }Syhi-подсветка кода


В результате вместо N+1 аллокаций памяти на один файл анимации, получил всего лишь 2.
Где N - количество кадров. Учитывая то, что анимации могут занимать весьма ощутимое количество памяти, это неплохой выигрышь. Причём тут куда важнее не скорость загрузки, хотя и она сильно возрасла, а то, что память меньше фрагментируется таким образом.