Home page of the programmer  

Домой

Программа для чтения электронных книг FictionBook
9 ноября 2009 13:32

Чуть больше года тому назад мое давнишнее увлечение чтением электронных книг привело меня к формату FictionBook, о программе для чтения которого и пойдет речь.

До этого я читал по большей части в PDF и CHM. Но первый задумывался как формат для печати со всеми вытекающими, а второй делался только для виндовоза. Хотя, и в других осях читать его можно, но это не наш путь. :-)

Через какое-то время мне попался на глаза FictionBook, и выбор пал на него - он мне понравился сразу. Формат изначально задуман для электронных книг и лишен неудобного наследства бумажных книг. Выбор программ для чтения оказался невелик - большинство только под виндовоз или мне не нравятся. А поскольку в Гноме на моей любимой FreeBSD читать толком не чем, решил написать свою.

Средства и инструменты долго выбирать не пришлось - уже давно подсел на GTK+ и Анюту. Для чтения XML-файла с книгой - libxml2 как хорошо проверенную временем и быструю библиотеку. Для хранения служебной и прочей информации - встраиваемую базу данных sqlite3. Все эти средства переносимы, стало быть, работают на разных платформах. С лицензией вопрос тоже не стоял - GPLv3.

Определимся с основными задачами, которые программа должна решать:

  • Полная поддержка формата - что, как оказалось, редкость (забегая вперед, скажу, что от поддержки CSS я все же отказался).

  • Закладки (автоматическое запоминание места, где закрыл книгу, плюс пользовательские закладки).

  • Навигация (оглавление, ссылки, вложения и история).

  • Библиотека (уже на 50-ти книгах я начал ловить себя на том, что ищу нужную мне книгу глазами, а когда их будет тысяча?).

  • Настройка отображения самой книги (формат, за небольшим исключением, не оговаривает способ отображения текста, возлагая эту задачу на программу для чтения).

  • Кое какие дополнительные функции, о которых пока промолчу.

    Кроме того, неплохо было бы реализовать интеграцию с Гномом. А это зарегистрированный в среде MIME-тип, ассоциация его с программой, предосмотр в Наутилусе (другими словами, в папках вместо иконки файла видна обложка книжки) и, конечно же, видимость программы в системном меню.

    Первая версия программы использовала технологию DOM как одну из самых простых. Суть DOM такова, что в памяти создается структура, полностью соответствующая файлу по иерархии и содержимому. А дальше эта структура читается программой, и из нее извлекаются данные. Прочитав пару десятков книг в своей еще не готовой до конца программе, я убедился, что DOM не совсем подходит для решения задачи. Во-первых, файл парсится минимум в два прохода, а это накладные расходы. Во-вторых, поскольку структура строится в памяти, расход памяти становится просто неприличным. В-третьих, ограничения технологии DOM, на которые я наткнулся, не давали реализовать задуманное простым и элегантным способом. В итоге я решил переписать программу заново с использованием технологии SAX. Это очень быстрая событийная технология, читающая XML-файл за один проход, использующая минимум памяти, а главное, ниже уровнем, чем DOM (SAX все равно работает внутри DOM, когда в памяти создается структура XML-файла). Программного кода в итоге получилось значительно больше, но скорость чтения ощутимо возросла. Плюс к тому, я учел опыт создания и использования первой версии.

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

    Исполняемый файл отдельной программы для показа обложек вместо иконок в Гноме получился чуть больше 10 Кб. Когда я прикрутил его к Гному, на папки с книгами стало приятно смотреть - прямо как в библиотеке. :-)

    В интерфейсе программы я старался следовать философии HIG, то есть простота и понятность интерфейса вкупе с продуманной организацией управляющих элементов. По совету разработчиков GTK+ я поглядывал на организацию интерфейса таких программ, как Evince и gedit (а на gedit еще и по организации программного кода). Что мне не нравится в аналогичных программах для чтения - так это большая привязка к формату, чем к интерфейсу. Этого я решил избежать. По моему мнению, читатель не должен и понятия иметь о внутренней структуре файла книги, но должен видеть перед собой очевидные и уже привычные из других программ инструменты.

    С самого начала разработки я отдавал себе отчет в том, что без программы-библиотеки мне не обойтись. Я реализовал ее как отдельное окно в программе плюс возможность запуска библиотеки отдельно от читалки с помощью ключа командной строки. Посмотрев на организацию интерфейса аналогичных программ, я получил неприятные впечатления. Во-первых, многошаговые операции с деревом (аля жанр -> автор -> серия -> книга), во-вторых, неочевидная организация интерфейса вообще (включая показ непосредственно книг), в-третьих, отсутствие пользовательских инструментов для управления библиотекой (я не имею в виду разного рода импорты-экспорты и прочие сторонние для библиотеки функции). Мне гораздо больше импонирует логика таких программ как Rhythmbox где можно самому организовать структуру свой библиотеки.

    Поскольку библиотека, да и сама программа в целом является однопользовательской, по моему мнению, логично использовать для хранения встраиваемую базу данных. Вот тут я открыл для себя sqlite3 - очень быстрая и мощная база данных (тут тебе и реляционные связи, и индексы, и проверки и прочие приятные мелочи, которые скорее ожидаешь увидеть в "тяжелых" СУБД). А коль скоро я задумал программу как межплатформенную, то решил хранить в sqlite3 вообще все: и пользовательские настройки, и закладки, и служебную информацию библиотеки. Дабы не плодить излишние сущности типа GConf или виндовозного реестра.

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

    Пользовательские настройки программы я решил разделить на общие и относящиеся непосредственно к книге. Дабы не усложнять настройку и соответствовать принципу KISS.

    От полной реализации стандарта я решил отказаться, а именно от реализации стилей CSS. Во-первых, какая именно из версий CSS должна поддерживаться спецификацией стандарта не оговаривается, во-вторых, верстальщиками книг почти не используется, а, в-третьих, в следующей версии формата стили планируется убрать (я узнал это от авторов формата).

    С таблицами вообще получилось забавно - авторы читалок говорят - зачем нам это реализовывать, если толком нету редакторов, которые их поддерживают, а авторы редакторов, в свою очередь, говорят - зачем нам это делать, если нету читалок, которые умеют читать таблицы. Замкнутый круг. :-) Тем не менее, сделать поддержку таблиц в своей программе я считаю необходимым.

    В итоге в настоящее время я занимаюсь доделкой разного рода "рюшечек", читать без которых можно, но неудобно, типа точной прокрутки с начала строки, а не с ее середины, выпадающих меню и тому подобного. Планирую закончить программу в ближайшее время.


    Версия для печати | Комментарии (9) | Добавить комментарий

  • Дополнительно

    Версия для печати

    Комментарии (9)






    Разделы блога

    InJoy Firewall (5)

    Веселые истории (1)

    Здоровье (4)

    Интернет (4)

    Личное (3)

    Разработки (1)

    События (1)

    Электронные книги (1)

    Последние статьи


    Самые читаемые

    Любителям клубнички

    Лечить фурункулы проще простого

    Зрение можно исправить!

    Подсчет трафика в InJoy Firewall 3.0

    Бережем здоровье при работе за компьютером


    Ошибка в тексте?

    Выдели ее мышкой и нажми Ctrl+Enter



    На благое дело
    ЯндексЯндекс. ДеньгиХочу такую же кнопку



    Рейтинг блогов