12

独自の小さなフローベースのレイアウト エンジンを実装しようとしています。HTML レイアウトの動作を模倣する必要がありますが、DOM 部分ではなくレンダリング ツリーのみを模倣する必要があります。render-tree の要素の基本クラスは Nodeclass です。それは持っています:

  • DOM 内の要素へのリンク (そのライブラリでレンダリング ツリーを構築するもの用)
  • その親への参照 (ContainerNodeインスタンスまたは None です。後述)
  • layouting-options への参照
  • X、Y、幅、高さ ( でlayout()サイズが計算された後、で位置が計算されcompute_size()ます。位置はlayout()親のメソッドで定義されますが、サイズはオプション リファレンスで定義されます)。

その方法は次のとおりです。

  • reflow()呼び出しcompute_size()layout()
  • compute_size()これは、ノードの幅と高さを計算するためのものです。
  • layout()これは、ノード自体ではなく、ノードのサブノードを配置するためのものです。
  • paint()これは、ライブラリのユーザーが上書きするためにあります。

このContainerNodeクラスは、サブノードの処理を実装しています。add_node()これは、渡されたノードをコンテナの子に追加する という新しいメソッドを提供します。forceが True に設定されている場合を除いて、コンテナは渡されたノードを拒否できるため、関数はデフォルトで False に設定されているパラメータforceも受け入れます。

これら 2 つのクラスは、レイアウト アルゴリズムを実装していません。私の目的は、さまざまなタイプのレイアウト用にさまざまなクラスを作成することでした (CSS では、主にdisplay属性によって定義されます)。昨夜、テキスト レイアウトでいくつかのテストを行いました。私のコードは、pastebin.com (pygame が必要) で見つけることができます。これを Python スクリプト ファイルに保存して、次のように呼び出すことができます。

python text_test block -c -f "Georgia" -s 15

注: コードは本当にくだらないものです。嘘の深い誤解についてのコメントに感謝します。

上記のコードのクラスInlineNodeRowは、属性に似たレイアウトのノードをdisplay:inline( と組み合わせてNodeBox) 実装する方法についての私の考えを実際に表しています。

問題 1 - インライン テキストのマージンとパディング

ライブラリでの現在のアプローチに戻ると、テキストの 1 つの単語も 1 つのノードとして表されます (上記のコードのように)。<span>しかし、タグのマージンとパディングについて 2 つのことに気付きました。

  1. マージンが設定されている場合、水平マージンのみが考慮され、垂直マージンは無視されます。
  2. パディングが親コンテナーをオーバーフローしており、スパン ノードを「移動」していません。

http://jsfiddle.net/CeRkT/1/を参照してください。

ここに問題があります。 のサイズを計算したい場合InlineNodeBox、テキストノードにそのサイズを尋ね、それをノードのサイズに追加します。ただし、テキストノードのサイズにはマージンとパディングが含まれており、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私が目にする次の問題は、テキストノードを正しくレイアウトするために、単語ごとに単一の s に分割したかったのですが、マージンとパディングはこれらすべてのノードに適用され、HTML のマージンとパディングは<span>タグのみです。

各単語を個別のノードに入れるという現在の考えは理想的ではないと思います。ブラウザがレンダーツリーを構築する方法、またはより良いアイデアはありますか?

問題 2 - 単語が長すぎます。次の行に入れます。

このクラスは現在、1 行InlineNodeBoxのみを編成しています。上記のコード例では、前者がノードの受け入れを拒否した (つまり、収まらなかった) ときに、新しいfromを作成しました。レンダー ツリーを最初から再構築したくないので、現在のアプローチではこれを行うことはできません。ノードが一度受け入れられたが、次のリフローで超えた場合、次の行に単語を適切に配置するにはどうすればよいですか (クラスがノードの単一行のみを編成するという考えを保持していると仮定します)。InlineNodeBoxNodeBoxInlineNodeBoxInlineNodeBox


これがすべて理にかなっていることを本当に願っています。私のコンセプトがわからない場合は、お気軽にお尋ねください。また、他の概念、リソースへのリンク、ドキュメント、出版物などに対する批判やアイデアにも非常にオープンです。

4

2 に答える 2

1

問題 2 :

HTML レンダラーが行うように、複数行をレンダリングすることができます (たとえば、追加する新しい単語が幅を超えているかどうかを確認し、超えている場合は新しい行を追加します)。InlineNodeRow高さも考慮し、最大幅を超える場合は単語をラップすることで、あなたの でそれを行うことができます。

問題 1 :

テキストの問題 2 を見つけた場合は、最初の行にのみオフセット (水平パディング) を入れることができます。

は考慮されてい<span>ませんが、必要なため、オプションが利用できない場合を除き、デフォルトの高さがフォントの高さであると計算される可能性があります。heightline-heightline-height

2 つ以上の連続したInlineNodeRow代表スパンがある場合は、最初のスパンが終了したところから 2 番目のスパンを継続させるためのスマートなロジックが必要になることに注意してください :)

補足として、Qt のリッチ テキスト labelから覚えていることから、同じレンダリング プロパティを持つ単語の各セットはノードと見なされ、その render 関数がすべてのものを計算します。あなたのアプローチはもう少し細かく、私が見た唯一の欠点は、単語を分割できないことです。

HTH、

于 2013-01-14T15:22:26.593 に答える
1

ボックス モデルのドキュメント問題 1の解決策が見つかった可能性があります (クリアランスに関するドキュメントと、問題 2のオーバーフローに関するドキュメントを確認することをお勧めします)。

"margins of absolutely positioned boxes do not collapse."

例として、この jsfiddleを確認できます。

于 2013-01-18T00:41:09.107 に答える