программирование
Brainf★ck в highlight.js
Как сохранять историю Skype
Мне сильно не нравится, когда собеседник удаляет в «Скайпе» свои сообщения. Бывает, что я их не успеваю прочитать, это печально. Я подумал, что было бы неплохо научиться их
К счастью, «Скайп» хранит свою историю в SQLite, а там, как оказалось, есть триггеры. В общем, простой способ сохранять историю — создать ещё одну таблицу и триггер, который будет висеть на операции INSERT и копировать все новые сообщения в нашу таблицу:
CREATE TABLE Messages_backup (timestamp int, author text, body_xml text); -- таблица, где будут храниться сообщения
-- А вот и наш триггер, причём посмотрите, после WHEN у меня идёт условие, я сохраняю только сообщения
-- от пользователя megadestroyer, это условие можно убрать (вместе с WHEN)
-- или написать туда через OR несколько логинов
CREATE TRIGGER Messages_insert INSERT ON Messages WHEN new.author='megadestroyer'
BEGIN
INSERT INTO Messages_backup VALUES(new.timestamp, new.author, new.body_xml);
END;Создать таблицу и тригер очень просто, база SQLite — это просто файл (вам нужен файл «main.db»), который лежит
После чего, если захочется прочитать что же удалил собеседник, там же, в sqlite3, можно будет выполнять команду
select * from Messages_backup;и видеть весь лог сообщений, включая удалённые пользователем.
Sleepsort
Из «Хабра» узнал про алгоритм sleepsort. Он больше забавный, чем практичный, я переписал его на баш:
while [ -n "$1" ]; do
( sleep "${1/%[0-9]/}.${1:(-1)}" ; echo "$1" ) &
shift
done
wait
echoСмысл в том, что запускается несколько параллельных процессов, по числу сортируемых значений, с паузой кратного значению размера. Вывод каждого из процессов происходит после истечения паузы, поэтому значения появляются в уже отсортированном виде:
$ bash sleepsort 1 2 7 10 3
1
2
3
7
10Firefox 16 CSS hack
.selector, _:-moz-meter-optimum {
background: red;
}int(?) в MySQL
Кто уверен, что точно знает что означает тип «int(11)» в MySQL? Я именно «интами» не пользовался никогда, всегда заводил через tinyint и т. п., поэтому, глядя на то СУБД в эти скобочки сама подставляет
Оказывается, это размер да не тот:
int(i) i — это не ограничение разрядности, int всегда одинаков -2³¹
до +2³¹-1 (или 0до 2³²-1), а ограничение количества показываемых символов при отображении столбца, его значение от 1 до 255. Например, INT(5) объявляет столбец целого типа который при отображении будет выводиться в колонках по пять цифр.Если в столбце реально записано значение которое нельзя отобразить
5-тью цифрами то оно будет отображено большим количеством символов, т. е. при выводе значение не усекается.
Так что будете заводить в следующий раз таблицу в MySQL, где идут подряд пять целых чисел, задайте им размерности 72, 101, 108, 108 и 111. Получится по кодам «Hello» в кодировке ASCII. Кто за вами потом разгадает, получит удовольствие.
Highlight.js+Brainfuck

Ура! Иван Сагалаев, автор прекрасной библиотеки для подсветки синтаксиса кода highlight.js (которую я использую на своём сайте), принял мой патч, приуроченный ко Дню программиста, для расцветки кода на языке Brainfuck. Радость!
Интерактив и CSS
Я считаю, что с появлением анимации в CSS, интерактивность, достигаемая без использования JavaScript вышла на новый уровень. После экспериментов с вложенными повернутыми структурами, мне стало интересно посмотреть как выглядит анимация таких структур, хороши они тем, что там надо анимировать всего один стиль, а структура сама будет выделывать всякие дикие штуки.
Например, если анимировать градус поворота, то получится забавный червяк, закреплённый с одного конца. Легко можно сделать, чтобы он ползал и извивался буквой «S», если бы целую кучу префиксов не приходилось писать.

Но самое потрясающее — возможность добавлять интерактив, жаль только возможности браузеров в этом пока очень ограничены. Попробуйте поводить курсором мыши по червяку и закон его движения изменится, причём совершенно без JavaScript! Изменится случайным порядком — всё зависит от того как вы проведёте мышкой.
Устройство простое (если убрать лишнее):
@keyframes wag {
50% {
transform: rotate(10deg);
}
}
сегментхвоста {
/* остальные стили */
transform: rotate(-10deg);
animation-name: wag;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
сегментхвоста:hover {
animation-name: none; /* отключаем анимацию, если навели мышкой */
}На наведение мышкой анимация отключается, от начала червяка до места наведения
Шрифт на чистом CSS
Десять лет назад я пытался решить проблему отсутствия у пользователей татарского шрифта (с Юникодом тогда было плохо, да и татарский туда не входил
Мощность компьютеров и возможности браузеров тогда были таковы, что такой HTML выводился буквально по слогам — компьютер нагружался сильно.
Сейчас такой проблемы нет, зато мощность компьютеров и браузеров возросли многократно. Я попробовал для интереса создать шрифт на чистом ЦСС. Там где можно пользовался только стилем бордюра, где нельзя — использовал

Правда я сделал ошибку — сначала создал все самые простые буквы, а потом уже начал делать сложные. Ближе к концу я начал терять интерес к происходящему и на некоторых буквах уже халтурил — некоторые из них отличаются по размеру.
Слова пишутся внутри тега TEXT, буквы повешены на однобуквенные теги, им соответствующие. Для наглядности, вот код, который напишет HELLO с моим стилем CSS:
<text><h></h><e></e><l></l><l></l><o></o></text>Цифр я изготовил всего две, они на тегах D1 и D8 (т. е. работают только однёрка и восьмёрка), кроме всего есть два знака препинания — точка (на теге DOT) и запятая (COMMA).
Обратите внимание, кстати, что в ИЕ можно такой шрифт создать уже с версии 5.5 — там есть фильтр matrix, при помощи которого можно эмулировать всё, что я использовал.
В ужатом состоянии (через оптимизатор CSSO) шрифт занимает всего 3,8КБ.
Вложено и повёрнуто

С тех пор как в браузерах появилась возможность свободно вращать любые объекты, мне нравится смотреть что из этого можно сделать, причём нравится экспериментировать с одинаковыми многократно вложенными объектами.
Т. е. поворот в CSS я задаю на один и тот же градус, но поскольку объекты вложены друг в друга, родительский угол тоже учитывается и получаются разнообразные кольца с регулярным рисунком. Если подключить к этому графику (тот же SVG), то всякие рождественские венки и прочие кольца со сложными, но повторяющимся рисунком, можно делать очень естественными образом.
Кстати, а если наложить несколько изображений с разным шагом и
Побочный эффект оператора «delete» в JavaScript
Как говорится «век живи, век учись, дураком помрёшь»:
Объяснение (по крайней мере для Хрома) очень простое: когда вы делаете delete testedObject[i].obj, V8 нормализует объект testedObject[i] — трансформирует его из быстрого компактного представления в медленное и раздутое представление на основе словаря, который еще и выделяется с запасом по размеру. При этом V8 не замечает, что после удаления в словаре будет пусто — и словарь (800 байтов) остается болтаться в воздухе. И так для каждого из ваших объектов.
Из коментария к статье на «Хабре», которая описывает странный эффект — при использовании оператора delete
ICC-профили в GIF
Формат ГИФ
Например, считается, что анимация появилась только в версии 89a (неправда, она была уже в версии 87a, в 89а её возможности были расширены), что ГИФ может использовать не более 256 цветов (не совсем так — не более 256 цветов на кадр, кадры могут накладываться друг на друга, давая любое отображаемое компьютером количество цветов).
Другое распространённое заблуждение — что ГИФ не поддерживает цветовые профили (ICC).
В самом деле, если посмотреть спецификацию формата, то слово «ICC» там не найдётся, но не найдётся там и слова «loop» (здесь: количество повторов), тем не менее, вы видели анимации, где указано определённое количество повторений и браузеры
Дело в том, что формат ГИФ поддерживает расширения. Расширения в спецификацию формата не входят.
Упомянутое количество повторов анимации задаётся в расширении, которое было
Вот начало файла ГИФ с внедрённым профилем:
00000000 47 49 46 38 39 61 01 00 01 00 f0 00 00 fe 00 02 |GIF89a……….| |
Пока не все браузеры умеют поддерживать цветовые профили ГИФ (как и профили любого другого формата), так ФФ не научился делать это до сих пор, а «Опера» научится это делать в новой версии 12.50.
Проверить поддерживает ли браузер цветовые профили можно и через Джаваскрипт. Принцип такой: я загружаю
Opera 12.50 CSS hack
Ребята из «Оперы» уже трудятся над весьма интересной версией 12.50 и у меня уже готов
@media (-o-min-device-pixel-ratio: 1/100) {
@media all {
body {
background: red; /* Opera 12.50+ */
}
}
}И ещё вариант:
_:-o-prefocus:fullscreen, body {
background: red; /* Opera 12.50+ */
}Вместо body надо подставить нужный вам селектор.
Удаляем расладку «U.S. English» из «Мака»
Артём Поликарпов написал рецепт как можно удалить из «Мака» раскладку «U.S. English». Она очень мешается и совершенно не нужна, если поставить великолепную раскладку Ильи Бирмана (кстати, если вы
Но рецепт Артёма мне не нравится тем, что для его выполнения приходится иметь у себя редактор Xcode, который ещё и несколько гигабайт весит. Поэтому я, как водится, написал скрипт, который нужно выполнить из «Терминала» (после его выполнения придётся опять залогиниться в систему) и ненужной раскладки уже не будет.
Какое счастье!
Проще всего скрипт запускать из «Терминала» вот так:
bash <(curl -fsSkL raw.github.com/bolknote/shellgames/master/us_layout_remover.sh)Чтобы вернуть всё обратно достаточно запустить программу ещё раз.
Добавлено позднее: удалению раскладки может мешать Punto Switcher.
До чего техника дошла

До чего техника дошла! У меня друг экзамен сдавал, когда упомянул про наушник, куда одногрупники будут начитывать билет, я, как мне показалось резонно, сказал ему, что не прокатит —
Найдите на картинке сам излучатель. Я попозже в комментариях расскажу что где.
Способ повалить Safari 6.0
Случайно нашёл способ как повалить браузер «Сафари» шестой версии (под «Мак»), другие версии не пробовал — не у меня их. Падает от такого HTML-кода:
<style>
* {
background: -webkit-image-set(url(BOLK!) 1x), url(BOOM!)
}
</style>Google Go GD binding
Исправил свой биндинг графической библиотеки GD к языку «Гоу» так, чтобы он работал под первой версией языка. Теперь изменился способ его установки и использования.
Ставить его теперь намного проще, достаточно выполнить следующую команду (в системе должна быть установлена библиотека GD):
go get github.com/bolknote/go-gdСпособ подключения бибилиотеки так же изменился (см. sample.go):
import gd "github.com/bolknote/go-gd"Надеюсь, больше «Гугл» библиотеки языка и способ сборки менять не будет.
Добавлено позднее: заодно портировал на Go 1 и свою программу MakeCorner, ставиться, опять же, стала попроще, а вот размер сильно вырос. Версия r60 компилировала файл размером 1,6МБ, версия 1 компилирует уже в 2,2МБ. Безобразие!
WEBP в PHP

Когда я делал биндинг GD для языка «Гугл Гоу», заметил, что в ПХП появилась поддержка формата WEBP. О самом формате
Чтобы поддержка формата (пока довольно куцая) появилась, нужно установить библиотеку libvpx и пересобрать ПХП с ключом
./configure --with-vpx-dir=/usr/local/Cellar/libvpx/1.1.0 \
… остальные опции
make
sudo make installПравда в phpinfo информация как у меня на картинке не появится (это я сам немного пропатчил исходники), не пугайтесь — так должно быть, проверить наличие поддержки WEBP можно следующим образом:
var_dump(function_exists('imagewebp'));Собственно, в языке появятся две новые функции: imagecreatefromwebp и imagewebp. У первой только одни аргумент — имя файла из которого надо создать ресурс GD (по действию ничем не отличается от любой другой подобной функции, например imagecreatefromjpeg), вторая принимает два параметра — ресурс и необязательные имя файла и качество, описание функции полностью совпадает с imagejpeg, с той только разницей, что сохраняет она формат WEBP.
Параметр качества изменяется от 0 до 100 и соотвествует параметру VP8 QP кодека в диапазоне от 1 до 63.
Сжатие GIF через gzip
Эксперимент мой сжатию несжатых ГИФ, по сути, провалился — если статические изображения иногда оказываются меньше (или сравнимы) с PNG, то с анимированными изображениями, ради которых всё и затевалось, всё плохо, я не сумел подобрать условия, при которых новоявленный метод обгоняет обычные соптимизированные ГИФы.
Зато я попутно выяснил, что ГИФ, вопреки моим ожиданиям, иногда жмётся gzip, на первой попавшейся анимации я получил выигрыш порядка 9%. Так что вот он метод ещё больше утоптать файлы ГИФ:
#!/bin/sh
which -s defluff
if [ $? -eq 0 ]; then
gifsicle -O3 "$1" | gzip -9nc | defluff 2>&- > "$2".temp
else
gifsicle -O3 "$1" | gzip -9nc > "$2".temp
fi
size=( $(ls -l "$2".temp) )
# срезаем заголовок gzip и контрольную сумму
let 'size=size[4]-10-8'
dd if="$2".temp of="$2" bs=1 skip=10 count=$size 2>&-
rm -f "$2".tempВ настройки Апача надо добавить новое расширение файла:
AddEncoding deflate .gif-def
AddType image/gif .gif-defДля браузера вместо gzip я указываю метод deflate — по факту это тот же gzip, но без заголовка и контрольной суммы, что позволяет сэкономить 18 байт, не бог весть сколько, конечно, но почему бы их не убрать, спрашивается.
Утилита defluff , которая у меня упоминается — это оптимизатор кодов Хаффмана для gzip, PNG и zip, иногда даёт выигрыш в размере.
Конвертор в несжатый GIF
Сделал я конвертор из обычного ГИФа в несжатый формат сжатый gzip, выложил на ГитХабе. Основное (разбор ГИФа) написано на Пайтоне, утилита, которая всё запускает — на Шеле. Для работы требуются ImageMagick (предпочтительнее) или gifsicle, gitinter (из libungif) и интерпретатор Пайтона.
Кажется, эксперимент провалился, я ещё буду вертеть различные ГИФы, но вряд ли
Из плюсов для себя: детально для себя разобрал формат GIF, освежил знания Пайтона (которые уже начинают тускнеть), Шела, поработал над интересной идеей.
Сжатый несжатый GIF
Как многие знают, браузер нативно понимает сжатие gzip (алгоритм DEFLATE).
Графический файлы обычно так не сжимают — внутри у них свой алгоритм сжатия, например в ПНГ используется тот же DEFLATE. Но с ГИФом ситуация хуже — у него внутри более старый алгоритм LZW, к тому же нет никаких оптимизационных техник (например, ПНГ использует так называемые «фильтры», которые позволяют эффективно сжимать градиенты.
Вот я и подумал — нельзя ли
Смотрите, слева у вас на экране ГИФ, сжатый при помощи gzip (так и грузится с сервера), справа — ПНГ.
![]()
![]()
В каждом из них равное количество уникальных цветов, ПНГ пропущен через все оптимизаторы, которые я только нашёл. При этом ПНГ занимает 1374 байта, а гзипованный ГИФ — 1347, на 27 байт меньше. Дело тут конечно, не в паре десятков байт, а в принципе — если бы я выбрал картинку побольше, выигрыш, возможно, был бы существеннее.
Почему же LZW внутри ГИФа, плюс DEFLATE снаружи сделали файл меньше, чем оптимизирующие просто DEFLATE, плюс фильтры в случае ПНГ? Обычно наложение одного сжимающего алгоритма на другой делает файл больше сравнению с применением одного, более удачного алгоритам из двоих.
Дело в том, что в ГИФ я использовал несжатый, он подготовлен специальным образом, так, что его собственный алгоритм сжатия не работает, а gzip работает над несжатым потоком данных.
Самый простой, по моему мнению, способ получить такой файл — пропустить его через утилиту gifinter из набора libungif — библиотеки и набора утилит для работы с несжатыми файлами ГИФ.
Утилиты эти отлично скомпилировались под мой «Мак» и обрабатывал я ГИФ следующим образом: для начала оптимизировал его при помощи giflite (эта старая утилита под DOS, которую я запускаю
gifinter optimized.gif > non-compressed.gif
gzip -9n non-compressed.gifДальше я переименовал файл
AddEncoding gzip .gif-gz
AddType image/gif .gif-gzТеперь при запросе сервер будет выдавать все необходимые заголовки:
bolk@Bolk ~ $ telnet bolknote.ru 80
Trying 91.230.61.15...
Connected to bolknote.ru.
Escape character is '^]'.
HEAD /imgs/2012.08.08.gif-gz HTTP/1.0
Host: bolknote.ru
Accept-encoding: gzip
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 08 Aug 2012 06:12:14 GMT
Content-Type: image/gif
Content-Length: 1347
Connection: close
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Expires: Fri, 07 Sep 2012 06:12:14 GMT
Content-Encoding: gzipЕсли интересно как устроен несжатый ГИФ, об этом можно прочитать в Википедии, откуда я взял картинку, там интересная уличная магия, перепечатывать «Википедию»
Готовой разгадки почему сжатый несжатый ГИФ обогнал ПНГ у меня нет, но есть одно возможное соображение — ГИФ