al_fuhrmann (al_fuhrmann) wrote,
al_fuhrmann
al_fuhrmann

Categories:

Рисование с помощью макросов

Различного рода документы иногда включают иллюстрации, которые сложно изобразить простыми средствами. Возьмем хотя бы обычную школу. Одна Марьиванна как-то пожаловалась на жизнь: в школе нет “специального” софта для учителей. - Я ехал на машине и вез двух училок, которые болтали на заднем сиденье о своих профессиональных делах. - Более того, школу “подсадили” на Linux (во времена реформ Медведева) и никто не знает, как с ним толком работать. В общем, у математички проблема: ей нужно сделать пособие для старших классов, где, по ее замыслу, должно быть много красивых иллюстраций с графиками функций, а “Mathcad”a в Linux'е нет”. Разумеется, все это педагоги делают в рабочее время в школе.

Так как я тоже когда-то учился в школе, и даже после школы изучал математику в университете, то я представляю себе примерно, что это за функции. Поэтому я удивился настолько, что влез в разговор. “Насколько я понимаю, это не такая уж большая проблема”. Одна из училок живо возразила: “А вы попробуйте сделать это в этом сраном Линуксе, с одним только его офисом”. Я сказал, что и пробовать не стану, а просто сделаю. “Мы вам пять пачек бумаги для принтера подарим, но надо, чтобы все работало!” Ок!

После того, как я забрал свой гонорар - пять пачек бумаги А4 по 500 листов для принтера - я подумал, что этот небольшой пустячок мог бы оказаться еще кому-либо полезным. Я делал эту работу так, чтобы в ней было “как можно меньше наворотов, только самое нужное”. Таково было ТЗ. Поэтому ее легко будет запостить.

Как небольшое вступление, я отмечу, что трудности вызывает “кошмарный” Basic в Open- и LibreOffice, к которому пользователи VBA не могут привыкнуть. То есть, собственно, не сам язык, он-то как раз всюду одинаков, а интерфейс UNO, придуманный в Sun Microsystems, на котором держится программирование для линуксовых офисов. Там за тысячу с лишним всяких сервисов и интерфейсов, и я тоже совсем не специалист по ним. Но у меня есть книжка Эндрю Питоньяка, где объясняются многие вещи. Есть даже ее перевод на русский, но в оригинале она более понятна.

Основная идея была в том, чтобы сделать костыль, скрыв “sun.star...” в понятной упаковке. В документе Draw присутствует хотя бы один лист, этого вполне достаточно. Функции рисуются макросом, а все остальное можно сделать вручную. Из всех примитивов берем только линию, а из ее бесчисленных атрибутов берем ширину и цвет.

В библиотечке всего две функции для рисования линий: по двум точкам и относительно предыдущей точки. Вторая очень удобна, потому, что имеет собственную, “плавающую систему координат”. Само собой, можно добавить и другие фигуры, а также множество всяких наворотов, так что приводимый пример - только минимум. Весь код, вместе с примером для теста, показан ниже, а дальше будет его небольшое обсуждение.

Код

Тест должен подтвердить, что косяков нет. Дальше скринкаст этого теста:



Теперь пояснения по коду вдобавок к комментариям. Они будут полезны тем, кто пожелает это использовать и, конечно, добавить сюда свои прибамбасы. Мы используем несколько переменных как public, для того, чтобы они были видимы в пределах модуля с библиотекой и макросами. Библиотечку и макросы лучше всего хранить в документе, используемом как шаблон для определенных целей. Для “защиты” мы выбираем настолько геморройные имена, что мало кому придет в голову их использовать. Например, вставляя знак подчеркивания после первой буквы имени. Благодаря этому, для пользователей библиотеки остается возможность выбирать нормальные имена.

Функция origin устанавливает начало координат. Фактически это просто ппараллельный перенос “мировых” координат, которые в документах OpenOffice.org начинаются с левого верха документов, и идут с шагом в одну сотую мм вправо, по оси x, и вниз, по оси y. Есть совершенно аналогичная функция lrs, которая делает то же самое для относительного построения линий.

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

Переменные pgs и pg не следуют правилу x_..., т.е. они не записаны, как следовало бы ожидать, как p_gs и p_g. Это не является какой-то магией, просто так получилось. Первая из них (pgs), кстати, этого и не требует, она вообще, private. Их мнемоника: pages и page. Дескриптор набора страниц pgs следует получать первым. Мы делаем это в инициализирующей функции dp0init (draw page 0 init). Здесь мы временно используем дескриптор pgs, для получения остального, а именно дескриптора pg, дающего доступ к странице с номером 0, первой страницы.

thiscomponent всегда указывает на текущий документ и является, своего рода, “корнем”, откуда берется остальное. Метод getdrawpages() позволяет инициализировать структуру pgs. Все желающие могут посмотреть, что там есть, используя встроенный в LibreOffice отладчик Basic IDE. Это касается и всех остальных переменных. Объект pgs, в свою очередь, использует метод getbyindex() для получения другого объекта pg, несущего информацию о странице с указанным номером. Его мы будем использовать неоднократно, поэтому он у нас public. Из остальной инициализации мы устанавливаем цвет линии и ее ширину. В общем, по существу, функция dp0init является конструктором, как говорят в объектных языках программирования.

Собственно линии создаются функцией l_init. lin - это дескриптор реально создаваемого объекта (который, кстати, не был объявлен при помощи dim, но Basic это разрешил). Рассмотрим, как инициализируется lin. Это опять thiscomponent.createinstance(“имя из иерархии uno”). Кстати, мы не проверили еще на значение null ни один из объектов, но это не должно приводить к проблемам; наш случай слишком прост, чтобы из пушки стрелять по воробьям. Создав линию, мы уж, заодно, присвоим ей некоторые атрибуты по нашему умолчанию. (Умолчания LibreOffice могут оказаться другими.)

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

Ввиду существенной разницы между передачей параметров по ссылке и значению, мы используем такой “косвенный” способ инициализации, который стоит рассмотреть подробно. Сначала pt - это просто имя. Интерпретатор Basic выделяет память для указателя (а что еще?). Затем, pt =  lin.position дает интерпретатору понять, сколько памяти выделить по этому указателю, так как lin.position - это уже вполне конкретные данные. Затем, при инициализации членов pt записываются данные в выделенную память. И только потом, присваивание lin.position = pt правильно иницииализирует lin. То же относится и к sz.

Манипуляции с координатами в функции line2p не должны казаться загадочными с точки зрения азов аналитической геометрии и положения абсолютного начала в документе, о чем уже говорилось.

Наконец, метод add добавляет данные в документ, что вызывает видимые изменения в нем. Функция linerel использует данные о предыдущей конечной точке, если она, конечно, была инициализирована, о чем не следует забывать. Затем вызывается line2p, и после этого конец созданного отрезка становится началом следующего. Теперь осталось только пользоваться библиотекой на здоровье, пополняя ее новыми инструментами. Или создать свою, если есть идеи.
Tags: draw, libreoffice, макросы
Subscribe

  • Xcircuit - 1

    Хочу рассказать о хорошем редакторе приципиальных схем. Как видно из названия, этот редактор сделан для X (только не надо путать это с десяткой), и…

  • Снайперский прицел (+бонус)

    Для поиска в интернете. Дикая вещь!! Пригодится всем, кто ищет информацию. Без всякой рекламной херни и гнилых ссылок. Однако, как говорил один мой…

  • Вдогонку к предыдущему посту

    Конечно, такой навороченный инструмент, как Meshlab, не может не содержать множество кнопочек и крутилок для поддержания нормального полета. Только…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments