LINUX.ORG.RU

SVG-подобный GUI на Rust: как правильно сделать?

 , ,


1

5

Есть у меня небольшое хобби - раз в полгода пытаться писать GUI на Rust. Вот в этом репозитории провожу эксперименты: https://github.com/exgui/exgui

Запустить примеры можно так:

cargo run -p examples --bin smile
cargo run -p examples --bin clock

Идея в том, чтобы сделать нечто похожее на SVG, но с возможностью автоматического размещения текста, или нечто похожее на HTML, но с поддержкой графических примитивов любой сложности.

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

Например, может быть задана следующая структура элементов:

rect()
    .width(100)
    .height(100)
    .child(text("Hello, circle "))
    .child(circle().radius(15))
    .child(text("! And welcome!"))
    .build()

Необходимо, чтобы layout, который имеется в Rect по-умолчанию, расположил корректным образом свои дочерние элементы внутри прямоугольника, построчно. При этом кругом он должен оперировать как одним целым, а текст воспринимать как набор элементов для размещения - отдельных слов.

Я так понимаю, для этого в рендере мне придется спуститься на уовень глифов, чтобы рассчитать нужные размеры. Отсюда вопрос: как это корректнее всего сделать, какими библиотеками пользоваться?

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

Ответ на: комментарий от anonymous

Скриптуха же, ладно бы оно в комплайн тайм без рантайма позволяло декларативно писать, но ведь нет.

anonymous
()
Ответ на: комментарий от anonymous

В качестве рендера пока использую сишный nanosvg.

Тонко.

Действительно тонко, nanosvg это менее 3000 строк кода библиотеки, и еще до 200 своих для отрисовки результата. И никаких зависимостей. А если взять какой-нибудь librsvg, то там бинарников будет в сумме на десятки мегабайт. Понятно, что nanosvg не может в текст, фильтры и т.п., но в большинстве случаев это и не надо.

Serral
()
Ответ на: комментарий от anonymous

Рендер, как и контроллер пользовательского ввода, можно будет сменить. Само ядро делается независимым от их реализаций.

freecoder
() автор топика

Из GUI либ существует только Qt. Отсюда и плясать.

Так вот, получается, что мне нужна поддержка неких layouts, которые должны единообразно уметь автоматически размещать как графические элементы

Вы описываете QML.

Я так понимаю, для этого в рендере мне придется спуститься на уовень глифов, чтобы рассчитать нужные размер

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

Для отрисовки самих глифов проще всего использовать font-kit, ака нативные либы. Но он жирный и куций.

RazrFalcon ★★★★★
()
Ответ на: комментарий от Serral

Понятно, что nanosvg не может в текст, фильтры и т.п., но в большинстве случаев это и не надо.

Наркомания over 9000. librsvg рисует SVG. nanovg рисует кривые. Интересно, почему librsvg весит больше? Загадка.

не может в текст

но в большинстве случаев это и не надо

GUI

Мой мозг ломаться.

RazrFalcon ★★★★★
()
Последнее исправление: RazrFalcon (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Наркомания over 9000. librsvg рисует SVG. nanovg рисует кривые. Интересно, почему librsvg весит больше? Загадка.

nanosvg справляется с современными иконками для GNOME/KDE, что достаточно для 99.99% десктопного гуя. Ну и nanosvg ничего не рисует, а librsvg не умеет в SVG по твоей же логике, т.к. не умеет всю спецификацию.

Мой мозг ломаться.

Т.е. ты думаешь, что твой мозг сломался не из-за того, что SVG используют для лайаута текста, а из-за того, что кто-то сравнивает разные библиотеки? Он уже был сломан.

Serral
()
Ответ на: комментарий от Serral

nanosvg справляется с современными иконками для GNOME/KDE, что достаточно для 99.99% десктопного гуя

Если вы про рисование цветных квадратиков - то да, тут успех. Но это не svg.

по твоей же логике, т.к. не умеет всю спецификацию

Логика сломана тут только у вас. nanovg поддерживает 1% спецификации, а librsvg ~60%. Есть разница?

Ну и спойлер, полной поддержки SVG вообще ни у кого нет.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

Если вы про рисование цветных квадратиков - то да, тут успех. Но это не svg.

Опять максимализм.

Логика сломана тут только у вас. nanovg поддерживает 1% спецификации, а librsvg ~60%. Есть разница?

Смотря для чего. Если говорить про веб, то 60% librsvg можно выкинуть на помойку. Если говорить про иконки, то там хватает и 1%. Есть, конечно, узкопрофильные направления, но там уже все индивидуально, и далеко не факт, что там каким-нибудь боком когда-нибудь применится librsvg.

Ну и спойлер, полной поддержки SVG вообще ни у кого нет.

Спасибо, кэп. А тут еще и SVG 2 на подходе.

Serral
()

Переизобретение QML полезно для ума.

Вы описываете QML.

Как в QML будет выглядеть такой пример?

rect()
    .width(100)
    .height(100)
    .child(text("Hello, circle "))
    .child(circle().radius(15))
    .child(text("! And welcome!"))
    .build()

Текст вместе с графикой должен разместиться внутри прямоугольника построчно.

freecoder
() автор топика
Ответ на: комментарий от Serral

Если говорить про веб, то 60% librsvg можно выкинуть на помойку.

Как будто у браузеров есть нормальная поддержка svg. Насмешили.

Есть, конечно, узкопрофильные направления

Съехал так съехал.

RazrFalcon ★★★★★
()

Скорее, это переизобретение Flex (Adobe Flash), там всё это давно было и прекрасно работало в браузерах, но нет, всё выкинули и теперь у нас голый 0, а точнее, жирные сайты на React в 8 Мбайт javascript’а

menangen ★★★★★
()
Ответ на: комментарий от RazrFalcon

Как будто у браузеров есть нормальная поддержка svg.

Речь не шла про «нормальную поддержку», речь шла про веб и svg.

Съехал так съехал.

Ты уже определись - ты или вы. А что касается «съехал», то озвучь свои варианты, где нужен librsvg. Я бы предложил дизайн, но вряд ли люди работающие с каким-нибудь Illustrator делают это для отрисовки результата через librsvg.

Serral
()
Последнее исправление: Serral (всего исправлений: 1)
Ответ на: комментарий от Serral

озвучь свои варианты, где нужен librsvg

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

RazrFalcon ★★★★★
()
Ответ на: комментарий от peregrine

Там несколько фундаментальных косяков, которые нельзя исправить.

Грубо говоря, не написав рендер SVG, писать оптимизатор противопоказано. У SVG слишком много edge cases.

Например, я не знал, что пустую группу/g нельзя удалять. Так как в некоторых случаях она может влиять на отрисовку.

Но наверное основная проблема в том, что я пытаюсь как можно меньше трогать оригинальную XML структуру - что нереально. Поэтому новая версия будет работать по принципу: парсим SVG - понимает что там нарисовано - сохраняем как считаем нужным. То есть итоговый SVG (сама структура) будет очень сильно не похож на исходный вариант.

RazrFalcon ★★★★★
()
Ответ на: комментарий от peregrine

Изначально для SVG, но в последующем будет в каждой GUI либе. Тот же ttf-parser уже большинством используется.

rustybuzz тоже очень ждут (как минимум два проекта). Но я уже 4-е месяца потратил, и там ещё 2-3 осталось.

RazrFalcon ★★★★★
()
Ответ на: комментарий от peregrine

Там для рендера RazrFalcon писал на расте вроде библиотеки для работы с SVG…

Теперь понятно почему его так разрывает в этом треде после упоминания библиотеки на C.

anonymous
()
Ответ на: комментарий от RazrFalcon

librsvg уже давно переписали на Rust.

А теперь хорошо подумай какие еще библиотеки были упомянуты в этом треде. Или ты в unsafe-неосознанку ушел?

anonymous
()
Ответ на: комментарий от RazrFalcon

И он не поддерживает SVG потому, что..?

anonymous
()
Ответ на: комментарий от anonymous

Переизобретение QML полезно для ума.

Не QML, а QtQuick, который с SVG связан примерно никак. Да и QtQuick по сути не взлетел. Все как писали на QtWidgets, так и пишут.

EXL ★★★★★
()
Ответ на: комментарий от EXL

Ага, написан в 2005 и ни разу не переписывался, тупо потому что времени нет.

unC0Rr ★★★★★
()
Ответ на: комментарий от cdshines
Rectangle {
  width: 100
  height: 100
  ColumnLayout {
    anchors.fill: parent
    Text {
      Layout.fillWidth: true
      text: "Hello, circle"
      wrapMode: Text.WrapAtWordBoundaryOrAnywhere
    }
    Rectangle {
      width: 15; height: 15
      radius: 15
      color: "white"
    }
    Text {
      Layout.fillWidth: true
      text: "! And welcome!"
      wrapMode: Text.WrapAtWordBoundaryOrAnywhere
    }
  }
}
unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

Этот вариант заработал, если ColumnLayout заменить на Column. Спасибо.

А почему там для рисования круга используется Rectangle?

Ну и все-таки это не совсем то, что я имел ввиду, так как круг всегда рисуется на отдельной строке, а не в потоке текста.

freecoder
() автор топика
Последнее исправление: freecoder (всего исправлений: 2)
Ответ на: комментарий от freecoder

Ох, я тут ошибся:

Текст вместе с графикой должен разместиться внутри прямоугольника построчно.

Не построчно, а в одном потоке с переносами на новую строку (word wrap). То есть графика должна интерпретироваться как слово.

freecoder
() автор топика
Ответ на: комментарий от fluorite

Формально он делает то, что я запросил в том сообщении, так что спасибо.

freecoder
() автор топика
Ответ на: комментарий от freecoder

То есть графика должна интерпретироваться как слово.

Ну SVG такое тоже не умеет. Это разве что html, но с кучей ограничений.

RazrFalcon ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.