Russian Qt Forum

Программирование => Общий => Тема начата: Юрий-В от Октябрь 05, 2022, 13:29



Название: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 05, 2022, 13:29
Добрый день коллеги !

Есть необходимость создания класса нового устройства рисования аналогичного QWidget, QPrinter, ... !
Цель - написание класса который позволит грузить в него svg и на выходе формировать списки примитивов QPainterPath::ElementType::... для конвертации их в g-code !
Понимаю что это взаимодействие классов QPaint + QPaintEngine + QPaintDevice ! Но вопрос именно в нюансах взаимодействия и реализации !

У кого есть опыт написания таких классов ? Нужны консультации по ходу реализации !

С уважением, Юрий.
ПС - уточню - решение задачи с помощью парсинга XML я знаю - но это это "не по феншую" Qt :) ! Хотелось бы реализовать именно через внутренний функционал Qt ! Тем более что он есть ...


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 05, 2022, 15:16
ни один класс из свг модуля не подходит? https://doc.qt.io/qt-5/qtsvg-module.html QSvgRenderer например.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 05, 2022, 15:57
Спасибо за ответ !

Интересны любые соображения по данной теме !

На сколько я понял из описания Paint System (https://doc.qt.io/qt-6/paintsystem.html) - класс методы которого можно перегрузить и тем самым можно получить примитивы рисования QPainterPath::ElementType::... это класс QPaintEngine !
Не совсем понятно как получить аналогичный результат от класса QSvgRenderer() ? Если не сложно - поясните пожалуйста !

На данный момент мое затруднение в том что мне не понятно как "связать" классы QPaint + QPaintEngine + QPaintDevice для решения этой задачи ! Вроде читаю доки но блин не понимаю !!! :) Ни одного вменяемого примера реализации пока найти не смог !

- как наследоваться и перегрузить методы QPaintEngine - понятно !
- ... остальное в процессе :) ...

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 05, 2022, 18:41
QSvgGenerator наследуется от QPaintDevice, тут уже ничего придумывать и не надо. если я правильно понимаю, достаточно унаследоваться от QSvgGenerator и перехватывать нужные методы. Либо наследоваться от QPaintDevice и поглядеть в исходники QSvgGenerator, чтобы сделать аналогично, но для вывода в нужный формат.
Цитировать
This paint device represents a Scalable Vector Graphics (SVG) drawing. Like QPrinter, it is designed as a write-only device that generates output in a specific format.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 05, 2022, 19:39
Может быть оно конечно и так ...

Но поглядев внимательно header этого класса я не совсем понимаю что именно и как можно перегрузить в этом классе для того что бы решить мою задачу ?!

Сам QSvgGenerator предназначен все таки для генерации svg файлов на основании отрисованых с помощью QPainter примитивов !

А моя задача как раз обратная - получение примитивов на выходе класса ! При том что на входе есть svg файл !

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 05, 2022, 20:02
могу лишь посоветовать открыть исходники QPainter и изучить как оттуда извлекать примитивы (если такая возможность вообще есть)


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 06, 2022, 12:26
Добрый день !

Спасибо за ответ !

И спасибо за совет !

Тут такое дело ! Я уже потратил какое то время в попытке проанализировать троицу классов и нашел возможность перегрузки методов ! По моему мнению делаются они в классе наследнике QPaintEngine !
QPainter же это класс рисовальщик (собственно и из названия оно логично следует :) ) !
 
На данный час мне не понятно как описать взаимодействие классов которые обеспечивают Paint System ?!

Это и является моей проблемой и соответственно моим вопросом ! :)

Вроде описание вижу - https://doc.qt.io/qt-6/paintsystem.html ! :)
И желание реализовать имею ! :)
Но видимо experience мягко говоря не достаточен !!! :)

С уважением, Юрий.
ПС Буду премного благодарен за высказывание любых мнений и соображений ! Ну а если кто то имеет такой опыт и может указать "путь истинный" готов отблагодарить ! :)


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 06, 2022, 16:22
Цитировать
Custom Backends
Support for a new backend can be implemented by deriving from the QPaintDevice class and reimplementing the virtual QPaintDevice::paintEngine() function to tell QPainter which paint engine should be used to draw on this particular device. To actually be able to draw on the device, this paint engine must be a custom paint engine created by deriving from the QPaintEngine class.
Цитировать
If one wants to use QPainter to draw to a different backend, one must subclass QPaintEngine and reimplement all its virtual functions. The QPaintEngine implementation is then made available by subclassing QPaintDevice and reimplementing the virtual function QPaintDevice::paintEngine().

судя по описанию, в наследнике QPaintDevice достаточно переопределить лишь один метод, а всю нужную логику написать в наследнике QPaintEngine. Далее при создании QPainter подавать ему своего наследника QPaintDevice.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 06, 2022, 16:43
Совершенно согласен с вашей точкой зрения ! :)

Таки да ! Я тоже так считаю !

В наследнике QPaintDevice переопределяем paintEngine() и создаем обьект наследника QPaintEngine (в котором в свою очередь преопределены виртуальные методы в которых мы и перехватываем примитивы рисования) !

Но как быть дальше что то я ...
:)

С уважением, Юрий.
ПС Могу выложить проект набросков ввиде архива ! Если оно конечно нужно ?


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 06, 2022, 17:02
Да ! Очень похоже что вы правы !
Судя по описанию класса QPicture (https://doc.qt.io/qt-5/qpicture.html) а он наследуется так же от QPaintDevice ! Класс наследника QPaintDevice скармливается QPainter ! И QPainter отрисовывает нужную svg'шку на QPaintDevice !
Осталось это разумно описать кодом ! :)


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 06, 2022, 17:04
дальше загружаем свой свг в QSvgRenderer и отрисовываем на свой QPaintDevice через https://doc.qt.io/qt-5/qsvgrenderer.html#render
Цитировать
Since the rendering is performed using QPainter, SVG drawings can be rendered on any subclass of QPaintDevice.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 07, 2022, 10:05
Добрый день !

Спасибо !

В общем идея понятна !
Буду пробовать реализовать !
По дальнейшему процессу или результату обязательно отпишусь !

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 12, 2022, 12:24
Добрый день !

После недолгого копания получился вот такой вот набросок - https://gitlab.com/z34x/codemaker.git

Что то конечно получилось ! Но вопросов поубавилось не значительно :) !  

И так :

1 Понимаю что наследование должно быть примерно такое.
2 Понимаю что применение объектов классов наследников QPaintDevice, QPaintEngine и QPainter должно происходить так.

3 Не понимаю как задать  линейные размеры наследнику QPaintDevice ! Логично бы было что бы именно наследник QPaintDevice имел бы виртуальные методы с помощью которых меняются параметры устройства на которое происходит вывод (линейные размеры, единицы измерения ...) ! Но понимаю что моя логика тут конфликтует с действительностью. :)
4. Не понимаю что нужно делать в методах begin() и end() при наследовании например классa QPaintDevice. :)

Так и хочется сказать - запишите меня на курсы по Qt :))))) ! Ну или растолкуйте невежде ...
Решения подобной задачки я к сожалению в сети не нашел, а научиться писать классы устройств очень хочется ! :)

Ну и как следствие - у меня получается конвертировать один из svg файлов который есть в subдиректории /in и его сконвертированный образ в /out ! Он называется Петя.svg ! Но не получается конвертировать остальные ! Причина мне понятна в остальных есть тег g< \> ! Но как решить эту проблему не понятно ! :)

Короче вопросов много ...

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 12, 2022, 14:31
наследовать QSvgRenderer особого смысла нет. остальное вроде верно, но я лишь по диагонали посмотрел.

2) иначе б Петю сконвертировать не получилось :)
3) думаю, надо такие методы добавлять самому. например, у QSvgGenerator можно контролировать size и resolution.
4) можно ничего не делать, зависит от личной необходимости

что там за g< \> не знаю, в спецификациях свг не разбираюсь. Для теста можно взять Qt пример, который загружает свг (ну или самому такое написать) и проверить отобразит ли он эти картинки. Также глянуть в документации какую спецификацию свг поддерживает Qt и в какой добавлен этот g< \>.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 12, 2022, 16:33
По QSvgRenderer - согласен ! Конечно ! Это обертка для себя ! :)

2) иначе б Петю ... - ну да ! Это для меня тоже понятно. Так же как и то что Qt понимает не только тег - g (тег g служит для группировки фигур по смыслу, чтобы поддерживать прозрачную структуру документа. Группа элементов может быть использована повторно.), но и все остальные нюансы современного стандарта SVG ! 

3) думаю, надо такие методы добавлять самому. например, у QSvgGenerator можно контролировать size и resolution. - ну да так и есть ! Но это у QSvgGenerator !
В моем случае в QSvgRenderer можно задать размер области рендеринга setViewBox() и соотношение сторон при отрисовке setAspectRatio() что тоже отлично ! Но где сделать корректировку например единиц изменения я пока не знаю.

4) можно ничего не делать, зависит от личной необходимости - спасибо за уточнение - в этом были сомнения ! Хотя из того что нашел в доках понял примерно так же !

что там за g< \> не знаю, в спецификациях свг не разбираюсь. Для теста можно взять Qt пример, который загружает свг - да, это косвенно я конечно проверил ! Более того в проекте я использую те же самые svg'шки для отрисовки их на QToolButton() ! Поэтому практически уверен что дело не в Qt ! Причина того что у меня не получается в отсутствии моего опыта в данном вопросе !

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 17, 2022, 12:04
Добрый день !

И так ! :)
Часть моих выходных была посвящена попытке решения моей головоломки ! :)

В результате :
- понятно что в SVG мешает моему коду конвертировать файлы - это transform="translate(... ...)" ! Файлы где нет трансформаций как раз и были тем успехом который у меня был с самого начала ! :)
Но я абсолютно уверен что это как раз из за того что я некачественно использую методы классов Qt Paint System ! Так как при работе например с QImage те же самые файлы рисуются отлично !
Я еще более убедился что нужно искать компетентной помощи у специалистов которые работают с SVG и могут проконсультировать по методам классов Qt Paint System или разбираться в исходном коде. :)))

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 24, 2022, 10:27
Добрый день !

Кто может подсказать как в Qt определить точки пересечения линий при отрисовке SVG ?
Есть ли какие то стандартные методы ?

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 24, 2022, 12:10
если у линий есть координаты начала и конца (т.е. это отрезки), то можно, например, через https://doc.qt.io/qt-5/qlinef.html#intersects


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 24, 2022, 13:42
Спасибо за ответ !

Ну с линией - таки да ! Я это видел ! И даже приходилось пользовать ...

Но в моей задачке не совсем линии :
      QPainterPath::ElementType::MoveToElement: - с этим все понятно.
      QPainterPath::ElementType::LineToElement: - с этим ну в общем то тоже.
      QPainterPath::ElementType::CurveToElement: - с этим нет !!!
      QPainterPath::ElementType::CurveToDataElement: - с этим нет !!!
да и сама проблемка не совсем о пересечении двух линий !

Скорее мне нужно получить точки пересечения рисуемого в данный момент элемента (QRect) с ранее отрисоваными элементами на QPaintDevice !
Как то так !

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 24, 2022, 14:27
наверное только свою логику писать. например, хранить массив QPolygonF чтоб вычислять их пересечения.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 24, 2022, 19:14
Ну да ! Сегодня пришел примерно к такому же выводу !!! :)
Только думаю что нужно проверять вновь создаваемый QPainterPath на пересечение с ранее созданными QPainterPath ! С помощью ::intersect(...), ::intersected(...), ::contains(...), ... !
Тут есть над чем подумать и поэкспериментировать ! :)

С уважением, Юрий.
ПС по результатам отпишусь позже


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 27, 2022, 15:04
Добрый день !

По ходу разбора Qt SVG появляется все больше нюансов и вопросов ! :)

1. Правильно ли я понимаю что получение текущего цвета которым отрисовываются фигуры и примитивы в методах QPaintEngine доступно через -
QPaintEngine::painter()->pen().color(); ?

2. Где и как можно получить имя текущего слоя если SVG файл многослойный ?

,,,

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: kambala от Октябрь 27, 2022, 17:23
1. звучит логично. pen — это цвет контура (линий), цвет заливки — brush


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Октябрь 27, 2022, 19:01
Ну да ! :)
Проверил в коде ! Вроде так и есть !

Где бы блин найти приличное описание ?
Вроде и хелпа много и обсуждений, но как только касаешься чего то что не на поверхности лежит прям ступор ! :)

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Ноябрь 06, 2022, 13:55
Добрый день !

Некоторое время занимался другими вопросами !

Ну и конечно параллельно по немногу этой темой ! :)

Сейчас понимаю что уперся в проблему работы с размерами svg ! Мои предположения о том что масштабирование происходит путем вызова QSvgRenderer::setViewBox(...) оказались не верными ! После копания в исходниках наследников QPaintDevice (QImage, QPrinter ...) понимаю что это устроенно не так прямолинейно ! Но вот реального понимания механизма пока нет !
Если есть соображения и советы - с удовольствием прислушаюсь !

С уважением, Юрий.


Название: Re: Создание нового устройства рисования ...
Отправлено: Юрий-В от Ноябрь 22, 2022, 16:56
Добрый день !

Кто может помочь с пониманием работы с QPaintDevice::metric(..) ?
Все что написано в документации я уже конечно прочел и попробовал ! :)
  - QPaintDevice::PdmWidth: - ширина в единицах хранения в svg; (на сколько я понимаю в пикселах) (берем из QSvgRenderer::defaultDevice(..))
  - QPaintDevice::PdmHeight: - высота аналогично
  - QPaintDevice::PdmWidthMM: - ширина в мм (берем из QSvgRenderer::viewBox(..))
  - QPaintDevice::PdmHeightMM:  - высота аналогично
  - QPaintDevice::PdmNumColors: - количество цветов для создаваемого устройства (константа из требований к устройству) - пусть будет например 16
  - QPaintDevice::PdmDepth: - количество битовых плоскостей (по докам) - тут не понятно - это бит на цвет или что ???
  - QPaintDevice::PdmDpiX: - dpi X логическая - тут мне не понятно !!!
  - QPaintDevice::PdmPhysicalDpiX: - dpi X физическая - аналогично !!!
  - QPaintDevice::PdmDpiY: - dpi Y логическая - аналогично !!!
  - QPaintDevice::PdmPhysicalDpiY: - dpi Y физическая - аналогично !!!
  - QPaintDevice::PdmDevicePixelRatio: - соотношение чего с чем ???
  - QPaintDevice::PdmDevicePixelRatioScaled: - аналогично !!!

Уверен что не понимаю идею которая заложена в управлении классом ! Если у кого то есть опыт работы с этим методом и соответственно с классом - буду очень признателен за любые подсказки !

С уважением, Юрий.
ПС Понятно что можно написать свои костыли к данному классу и заставить его генерировать то что нужно ! Но хотелось бы именно разобраться в той логике которую закладывали разработчики.