Я пытаюсь реализовать свой собственный механизм макетирования на основе потока. Он должен имитировать поведение макета HTML, но только дерево рендеринга, а не часть DOM. Базовым классом для элементов в дереве рендеринга является класс Node
. Он имеет:
- Ссылка на элемент в DOM (для тех, которые создают дерево рендеринга с этой библиотекой)
- Ссылка на него parent (который является экземпляром
ContainerNode
или None, см. ниже) - Ссылка на параметры компоновки
- X, Y, ширина и высота (позиция вычисляется в
layout()
, после того, как размер был вычислен вcompute_size()
. Хотя позиция определяется методомlayout()
родителя, размер определяется например, с помощью ссылки на опции).
Его методы:
-
reflow()
вызовcompute_size()
иlayout()
-
compute_size()
, который предназначен для вычисления ширины и высоты node. -
layout()
, который предназначен для размещения суб-узлов node, а не самого node. -
paint()
, который должен быть перезаписан пользователем библиотеки.
Класс ContainerNode
реализует обработку под-узлов. Он предоставляет новый метод под названием add_node()
, который добавляет прошедшие node к детям контейнеров. Функция также принимает силу параметра, которая по умолчанию имеет значение False, потому что контейнеру разрешено отклонить переданный node, за исключением того, что для силы установлено значение True.
Эти два класса не реализуют никакого алгоритма компоновки. Моя цель заключалась в создании разных классов для разных типов макетов (в CSS, в основном определяемых атрибутом display
). Я провел несколько тестов с компоновкой текста прошлой ночью, и вы можете найти мой код с pastebin.com (требуется pygame). Вы можете сохранить его в файле python script и вызвать его следующим образом:
python text_test block -c -f "Georgia" -s 15
Примечание. Код действительно действительно дерьмовый. Я ценю комментарии к глубоким ложным заблуждениям.
Класс InlineNodeRow
из упомянутого выше кода фактически представляет мою идею о том, как реализовать node, который отличается от атрибута display:inline
(в сочетании с NodeBox
).
Проблема 1 - Маржа и заполнение для встроенного текста
Вернуться к моему текущему подходу в библиотеке: одно слово из текста также будет представлено в виде единственного node (как в приведенном выше коде). Но я заметил две вещи о полях и paddings в теге <span>
.
- Когда задан край, учитывается только горизонтальный запас, вертикальное поле игнорируется.
- Прокладка переполняет родительский контейнер и не "перемещает" диапазон node.
См. http://jsfiddle.net/CeRkT/1/.
Я вижу проблему здесь: когда я хочу вычислить размер InlineNodeBox
, я запрашиваю для него текст node и добавляю его к размеру node. Но размер текстовых узлов включает в себя его margin и padding, которые не включены в позиционирование рендеринга HTML. Поэтому следующий код будет неправильным:
def compute_size(self):
# Propagates the computation to the child-nodes.
super(InlineNodeBox, self).compute_size()
self.w = 0
self.h = 0
for node in self.nodes:
self.w += node.w
if self.h < node.h:
self.h = node.h
node.w
будет включать маржу и дополнение. Следующая проблема, которую я вижу, заключается в том, что я правильно определяю текстовые узлы, я хотел разбить их на одиночный TextNode
для каждого слова, но маржа и дополнение будут применены ко всем этим узлам, тогда как маржа и отступы в HTML только тег <span>
.
Я думаю, что моя нынешняя идея помещать каждое слово в отдельный node не идеальна. Как браузеры структурируют свое дерево рендеринга, или у вас есть идея?
Проблема 2 - Слишком длинное слово, поместите его в следующую строку.
Класс InlineNodeBox
в настоящее время организует только одну строку. В приведенном выше примере кода я создал новый InlineNodeBox
из NodeBox
, когда первый отказался принять node (что означает, что он не вписывается). Я не могу этого с моим текущим подходом, так как я не хочу снова создавать дерево рендеринга. Когда a node был принят один раз, но превышает InlineNodeBox
при следующем переплаве, как мне правильно поместить слово в следующую строку (предполагая, что я придерживаюсь идеи класса InlineNodeBox
только для организации одной строки узлов)?
Я действительно надеюсь, что все это имеет смысл. Не стесняйтесь спрашивать, не понимаете ли вы мою концепцию. Я также очень открыт для критики и идей для других концепций, ссылок на ресурсы, документации, публикаций и т.д.