Pull to refresh

Другой Open Source

Reading time7 min
Views2.4K
Тогда никто этих слов не употреблял. Не уверен, что я тогда вообще знал их значение. Впервые о проекте Владимира Кладова «Key Object Library», или просто KOL я узнал еще до института, в одном из двух выпусков журнала «Программист», которые моя мама выписала мне в честь выезда на олимпиаду по программированию в область. Статья называлась «Кол в сердце… своей программы!» Кажется в том же выпуске журнала, я впервые узнал и о .NET. Тогда, такие непомерные требования к ресурсам казались чуть ли не диверсией софтверного гиганта против IT индустрии. (До сих пор вспоминаю лабораторную друга-однокурсника, состоящую из одной формочки, запускающуюся пол минуты на кафедре на железе Celeron 433 64мб ОП из под 98-й винды. Я на той машине еще в Diablo II без тормозов играл, когда задание на пару было выполнено :)

А KOL был другой. Он ставил во главу угла скорость работы и размер исполняемого файла. Негоже было в то время качать из интернета обновления программ по 10 мегабайт каждое. Для тех, что писал под Delphi, выбор был не велик — либо использовать VCL — стандартную визуальную библиотеку Delphi (кстати, её архитектор так же работал над созданием .NET framework), либо писать на windows API, этим занимались самые отчаянные энтузиасты.

Не сказать, чтобы VCL был ужасен, он отлично справлялся с проектами от средних до огромных. Но для мелких утилит, которых начинающий программист пишет большинство, он подходил не в полной мере. Минимальный размер исполняемого файла был, в зависимости от версии Delphi от 250 до 350 кб и довольно шустро увеличивался с добавлением в приложение различных контроллов. Это было следствием, прежде всего, сильно разветвленного дерева классов, где у каждого контролла было до десятка родителей. Кроме того, я не мог простить VCL того, что пустое приложение на нем на моем самом первом компьютере AMD K5-100 запускалось около пол секунды, а приложение на MFC (стандартный фреймворк в старых визуал студиях) запускалось практически мгновенно :)

Видимо Владимира Кладова волновали те же проблемы и в какой-то момент он принялся за написание XCL — библиотеки, построенной на тех же принципах, что и VCL, но бережно относящейся к размеру исполняемого файла. А нужно сказать, что способов повлиять на размер экзешника достаточно много (не считая пост-обработки в виде упаковщиков). Разный код, выполняющий одну и ту же задачу, может сильно различаться в размере. Впрочем, работа над этим проектом продлилась не долго (судя по истории изменений, год), когда неэффективность этого подхода стала очевидной. Новой попыткой переосмыслить устройство компактного фреймворка был KOL.

Основное know how подхода KOL было в заточении функционала всех стандартных элементов управления в одном классе PControl. На первый взгляд это кажется бредом, когда за дерево каталогов и кнопку отвечает один класс, но это работало. Весь секрет был в разных конструкторах для разных контроллов. Довеском ко всему было MCK — надстройка над VCL, генерировавшая на выходе код для создания аналогичных KOL-компонентов. Т.е. вы могли работать в привычной среде Delphi, бросать на форму кнопочки, а MCK генерировало вам код для такой-же формы, но на чистом KOL. При этом стартовый размер приложения был 20 кб или 10 кб с небольшим ухищрением, заменой системных библиотек Delphi, которое можно было применять в «релизах».

Сообщество, развивающее библиотеку было небольшим, но дружным. Самый большой вклад в развитие библиотеки, конечно делал Владимир, но и роль других переоценить было сложно. В этот дружный коллектив, еще совсем зеленым я влился на первых курсах института. Главный форум, по совместительству баг-трекет, был на сайте delphimaster.ru. Коммиты, в виде дифов, сделанных с помощью написанной Владимиром утилитки, делали все заинтересованные (до сих пор не знаю, совместим ли её формат дифов с другими open source аналогами). Новые версии выпускал наш бессменный тимлидер. Лицензия, под которой можно пользоваться библиотекой, кажется, никогда на обсуждалась. На официальном сайте до сих пор написано простое и понятное «Предоставляется бесплатно, с исходными текстами».

Под фреймворк было написано и портировано очень много вспомогательных библиотек, все с соблюдением идеологии основной.

Как и в любом другом Open Source проекте, каждый находил в его развитии что-то свое. У Владимира было и есть довольно много небольших и средних проектов, все построенные на KOL:
  • ImgSearch — Программа для поиска и удаления похожих изображений. В свое время работала лучше, возможно известной вам imageDupeless.
  • Zoomer — (Осторожно, что-то мне подсказывает, что на странице вирус. Сама программа в порядке). Быстрый, даже очень, просмотрщик графических файлов со своим уникальным алгоритмом масштабирования, использующим MMX, который Владимир не согласился выдать даже под пытками :)
  • EmuZWin — Эмулятор Спектрума (S48 и S128). Поддерживает Multicolor (48K, 128, 128/+2/+3, Pentagon), Smooth Scale, и еще очень длинный список других штук :)
Эти и другие, более мелкие приложения можно найти на странице с программами на KOL. Как не однократно говорил сам Владимир, библиотека активно используется им на его основной работе.

У меня, понятно же, цели был совсем другие. Для меня это была прежде всего практика в программировании. Ну и как сейчас принято говорить just for fun. В библиотеку я внес всего 4 более менее значительных вклада. Так как я все равно не помню хронологии, перечислю их в возрастающем порядке значимости.

Новая отрисовка для контролла GradientPanel

Причина написания — очень медленная скорость предыдущей реализации. Так как новая не поддерживала некоторые виды заливки, которые поддерживала старая реализация, не была включена по умолчанию.

Библиотека tinyPictures

Конечно, это была не первая и даже не лучшая библиотека для загрузки картинок под KOL. Но она была очень хитрой :) Загрузчик форматов BMP JPG и GIF занимал не более одного килобайта в скомпилированном ввиде. Как такое возможно? Использовалась функции OLE-автоматизации OleLoadPicture. Конечно, это был не вариант для графических редакторов, как минимум эта функция не могла загружать битые картинки. Но для какого-нибудь установщика было самое то. А вот с PNG все было сложнее. Конечно, я брал за основу какую-то библиотеку не под KOL (даже не вспомню, какую), но на свою голову я тогда нашел набор картинок для тестирования PNG и многие форматы не работали. Пришлось дописывать. Тогда я узнал, на что способен формат PNG и какой он разный бывает (привет, ie!).

Замена старой системе прозрачности

KOL позволял любому элементу рисовать себя любой формы. То, что реализовал Владимир, а позже я улучшил не было в VCL кроме как для безоконных контроллов (т.е. картинок и лейблов). Мое улучшение было в следующем: раньше прозрачный элемент рисовал на себе родительский, а потом сверху себя. Если прозрачных элементов было 20, каждый из них рисовал на себе родителя. Мое решение было не рисовать дочерние элементы, а отсылать запрос на перерисовку родителю, который на себе отрисует всех детей. Звучит просто, но на сомом деле заставить делать GDI что-то, для чего он не был предназначен, было очень сложно. Тем не менее, достигнутый результат, кажется, корректно работал не менее чем в 90% случаев и работал быстрее предыдущего варианта.

GRush controls

До сих пор это самый большой проект, выполненный мной в одиночку. Кто-то из участников форума как-то продемонстрировал свои наработки по портированию на KOL библиотеки RB Controls. К слову, оригинальные RB Controls используются как минимум в одной из надстроек над IE (maxthon, кажется). Демо портированных компонентов выглядело так:

image

Согласитесь, довольно приятно. Плюс неплохие возможности кастомизации. Но вот скорость всего этого была далеко не потрясающей (можно посмотреть скомпилированный пример). Как я понял, оригинальные RB для VCL так-же не блестали. Дальнейшие мои действия угадать не сложно, я стал работать над своей версией контроллов, похожих на RB Controls внешне, но совершенно других внутри — GRush Controls.

В итоге получились контроллы с несколькими типами заливки, плавным перетеканием при нажатии и наведении, сглаженными круглыми уголками (привет, css3!), с возможностью использовать как текст с тенью, так и рисунок. И все это работало адски быстро даже на моем тогдашнем Celeron 500. В набор компонентов вошли: Button, Panel, CheckBox, RadioBox, Splitter (ползунок для изменения размеров пользователем 2-х других компонентов), ProgressBar.

В работе пригодились наработки по первому проекту, быстрой градиентной заливке. Все критические участки тщательно тестировались и многое было написано на ассемблере с применением MMX. Перечитывая сейчас некоторые пункты чейнджлога, такая ностальгия берет:
[+] Добавлен символ условной компиляции USE_MEMSAVEMODE (включен по умолчанию). Думаю все-же не так накладно с точки зрения производительности создавать новые Paterns при наведении или нажатии мыши, а удалять сразу как они не будут нужны. В больших проектах может сильно уменьшить количество используемой памяти (и видео кстати тоже).
[*] Процедура BitmapAntialias4X переведена в MMX на асамблер (прирост ее скорости вдвое), что однако не сильно увеличило общую производительность при больших значениях XXX_BorderRoundWidth/Height. По видимому узкое место - GDI, поэтому добавлена функция BitmapAntialias2X (в том числе и с MMX) и по умолчанию теперь используется она (если конечно не отключен новый символ условной компиляции USE_2XAA_INSTEAD_OF_4XAA).

Приведу несколько «шокирующих» фактов:
— Демка RB Controls при разворачивании на весь экран кушает у меня 7 метров памяти и до 50 во время изменении размеров панелей с помощью сплиттера.
— Демка GRush практически такая-же (скомпилированный пример) при любом размере окна кушает 850 Кб и во время изменения размеров до 3-х Мб. Секрет в использовании для неизменяемых поверхностей видео памяти, для изменяемой — dib.
— Градиентная панель размером 1900×1100 пикселей (такая) со скругленными, четырехкратно глаженными уголками 100×100 пикселей каждый, способна отрисовываться 70 раз в секунду. Без круглых углов до 320 раз. Это на одном ядре Athlon 5200. Нужно сказать, что это отрисовка «с нуля», которая происходит при изменении размеров компонента или создании. Если компонент никто не трогает, он рисует себя с кеширующей поверхности намного быстрее.

Отдельного упоминания стоят визуальные мастера настройки компонентов в MCK. Как я уже говорил, MCK компоненты по сути являются такими же VCL компонентами. Это не играет большую роль для кнопок и панелек, и те и другие есть в обоих фреймворках (KOL и VCL). А вот GRush controls для VCL нет, а настроек у них куча. И чтобы сделать полноценный редактор мне пришлось бы их портировать на VCL. Сама идея не плохая, но не ради же редактора настроек! Я поступил по другому. Насколько я знаю, до меня, а возможно и после, никто так не поступал. Я запустил в качестве редактора KOL-форму с настоящими GRush контроллами. Т.е. форма KOL работала в самой среде Delphi. Редактор получился таким:

image

Кажется я рассказал все, что собирался. Рассказ был навеян вчерашним опросом на хабре, «Есть ли для вас авторитеты в программировании», который, видимо, автор предпочел скрыть (Опросы у нас традиционно минусуются, да).

Кстати, случайно наткнулся на своем старом ftp на один интересный архивчик. Не уверн даже, что я сам его делал. В нем несколько демо-проектов на VCL vs KOL и VCL&RB vs KOL&GRush. Можете сами сравнить размер программ, скорость загрузки и потребление память.
Tags:
Hubs:
Total votes 89: ↑70 and ↓19+51
Comments53

Articles