Diff
diff --git a/cstyle/main.go b/cstyle/main.go
index b9ab091..ccd95c8 100644
--- a/cstyle/main.go
+++ b/cstyle/main.go
@@ -24 +24 @@ type Plugin struct {
- Handler func(*element.Node, *map[string]element.State)
+ Handler func(*element.Node)
@@ -119,0 +120,4 @@ func (c *CSS) GetStyles(n element.Node) map[string]string {
+func (c *CSS) Render(doc element.Node) []element.Node {
+ return flatten(doc)
+}
+
@@ -124,4 +128 @@ func (c *CSS) AddPlugin(plugin Plugin) {
-func CheckNode(n *element.Node, state *map[string]element.State) {
- s := *state
- self := s[n.Properties.Id]
-
+func CheckNode(n *element.Node) {
@@ -129,8 +130,8 @@ func CheckNode(n *element.Node, state *map[string]element.State) {
- // fmt.Printf("ID: %v\n", n.Id)
- // fmt.Printf("Classes: %v\n", n.ClassList.Classes)
- fmt.Printf("Text: %v\n", self.Text.Text)
- fmt.Printf("X: %v, Y: %v\n", self.X, self.Y)
- fmt.Printf("Width: %v, Height: %v\n", self.Width, self.Height)
- // fmt.Printf("Styles: %v\n\n\n", n.Style)
- // w := utils.GetWH(*n)
- // fmt.Printf("Calc WH: %v, %v\n\n\n", w.Width, w.Height)
+ fmt.Printf("ID: %v\n", n.Id)
+ fmt.Printf("Classes: %v\n", n.ClassList.Classes)
+ fmt.Printf("Text: %v\n", n.InnerText)
+ fmt.Printf("X: %v, Y: %v\n", n.Properties.X, n.Properties.Y)
+ fmt.Printf("Width: %v, Height: %v\n", n.Properties.Computed["width"], n.Properties.Computed["height"])
+ fmt.Printf("Styles: %v\n\n\n", n.Style)
+ w := utils.GetWH(*n)
+ fmt.Printf("Calc WH: %v, %v\n\n\n", w.Width, w.Height)
@@ -139 +140 @@ func CheckNode(n *element.Node, state *map[string]element.State) {
-func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State) *element.Node {
+func (c *CSS) ComputeNodeStyle(n *element.Node) *element.Node {
@@ -146,8 +146,0 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- s := *state
- self := s[n.Properties.Id]
- parent := s[n.Parent.Properties.Id]
-
- self.Background = color.Parse(n.Style, "background")
-
- fs, _ := utils.ConvertToPixels(n.Style["font-size"], parent.EM, parent.Width)
- self.EM = fs
@@ -156,4 +149,4 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- self.X = 0
- self.Y = 0
- self.Width = 0
- self.Height = 0
+ n.Properties.X = 0
+ n.Properties.Y = 0
+ n.Properties.Computed["width"] = 0
+ n.Properties.Computed["height"] = 0
@@ -167 +160 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- x, y := parent.X, parent.Y
+ x, y := n.Parent.Properties.X, n.Parent.Properties.Y
@@ -174,3 +166,0 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- self.Margin = m
- self.Padding = p
-
@@ -178,2 +168 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- bas := utils.GetPositionOffsetNode(n)
- base := s[bas.Properties.Id]
+ base := utils.GetPositionOffsetNode(n)
@@ -181,2 +170,2 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- v, _ := utils.ConvertToPixels(n.Style["top"], self.EM, parent.Width)
- y = v + base.Y
+ v, _ := utils.ConvertToPixels(n.Style["top"], float32(n.Properties.EM), n.Parent.Properties.Computed["width"])
+ y = v + base.Properties.Y
@@ -186,2 +175,2 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- v, _ := utils.ConvertToPixels(n.Style["left"], self.EM, parent.Width)
- x = v + base.X
+ v, _ := utils.ConvertToPixels(n.Style["left"], float32(n.Properties.EM), n.Parent.Properties.Computed["width"])
+ x = v + base.Properties.X
@@ -191,2 +180,2 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- v, _ := utils.ConvertToPixels(n.Style["right"], self.EM, parent.Width)
- x = (base.Width - width) - v
+ v, _ := utils.ConvertToPixels(n.Style["right"], float32(n.Properties.EM), n.Parent.Properties.Computed["width"])
+ x = (base.Properties.Computed["width"] - width) - v
@@ -196,2 +185,2 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- v, _ := utils.ConvertToPixels(n.Style["bottom"], self.EM, parent.Width)
- y = (base.Height - height) - v
+ v, _ := utils.ConvertToPixels(n.Style["bottom"], float32(n.Properties.EM), n.Parent.Properties.Computed["width"])
+ y = (base.Properties.Computed["height"] - height) - v
@@ -204,2 +193 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- sib := n.Parent.Children[i-1]
- sibling := s[sib.Properties.Id]
+ sibling := n.Parent.Children[i-1]
@@ -207,2 +195,2 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- if sib.Style["display"] == "inline" {
- y = sibling.Y
+ if sibling.Style["display"] == "inline" {
+ y = sibling.Properties.Y
@@ -210 +198 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- y = sibling.Y + sibling.Height
+ y = sibling.Properties.Y + sibling.Properties.Computed["height"]
@@ -213 +201 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- y = sibling.Y + sibling.Height
+ y = sibling.Properties.Y + sibling.Properties.Computed["height"]
@@ -218,2 +206,3 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- vState := s[v.Properties.Id]
- y += vState.Margin.Top + vState.Margin.Bottom + vState.Padding.Top + vState.Padding.Bottom + vState.Height
+ mc := utils.GetMP(v, "margin")
+ pc := utils.GetMP(v, "padding")
+ y += mc.Top + mc.Bottom + pc.Top + pc.Bottom + v.Properties.Computed["height"]
@@ -240,0 +230,25 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
+ bold, italic := false, false
+
+ if n.Style["font-weight"] == "bold" {
+ bold = true
+ }
+
+ if n.Style["font-style"] == "italic" {
+ italic = true
+ }
+
+ if n.Properties.Text.Font == nil {
+ f, _ := font.LoadFont(n.Style["font-family"], int(n.Properties.EM), bold, italic)
+ letterSpacing, _ := utils.ConvertToPixels(n.Style["letter-spacing"], n.Properties.EM, width)
+ wordSpacing, _ := utils.ConvertToPixels(n.Style["word-spacing"], n.Properties.EM, width)
+ lineHeight, _ := utils.ConvertToPixels(n.Style["line-height"], n.Properties.EM, width)
+ if lineHeight == 0 {
+ lineHeight = n.Properties.EM + 3
+ }
+
+ n.Properties.Text.LineHeight = int(lineHeight)
+ n.Properties.Text.Font = f
+ n.Properties.Text.WordSpacing = int(wordSpacing)
+ n.Properties.Text.LetterSpacing = int(letterSpacing)
+ }
+
@@ -246 +260 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- genTextNode(n, &innerWidth, &innerHeight, p, state)
+ genTextNode(n, &innerWidth, &innerHeight, p)
@@ -252,4 +266,4 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- self.X = x
- self.Y = y
- self.Width = width
- self.Height = height
+ n.Properties.X = x
+ n.Properties.Y = y
+ n.Properties.Computed["width"] = width
+ n.Properties.Computed["height"] = height
@@ -257,4 +271 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- (*state)[n.Properties.Id] = self
- (*state)[n.Parent.Properties.Id] = parent
-
- // CheckNode(n, state)
+ CheckNode(n)
@@ -267 +278 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- n.Children[i] = *c.ComputeNodeStyle(&v, state)
+ n.Children[i] = *c.ComputeNodeStyle(&v)
@@ -269,8 +280,9 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- cState := s[n.Children[i].Properties.Id]
- if n.Children[i].Style["position"] != "absolute" && cState.Y > childYOffset {
- childYOffset = cState.Y
- self.Height += cState.Height
- self.Height += cState.Margin.Top
- self.Height += cState.Margin.Bottom
- self.Height += cState.Padding.Top
- self.Height += cState.Padding.Bottom
+ if n.Children[i].Style["position"] != "absolute" && n.Children[i].Properties.Y > childYOffset {
+ childYOffset = n.Children[i].Properties.Y
+ m := utils.GetMP(n.Children[i], "margin")
+ p := utils.GetMP(n.Children[i], "padding")
+ n.Properties.Computed["height"] += n.Children[i].Properties.Computed["height"]
+ n.Properties.Computed["height"] += m.Top
+ n.Properties.Computed["height"] += m.Bottom
+ n.Properties.Computed["height"] += p.Top
+ n.Properties.Computed["height"] += p.Bottom
@@ -282,2 +293,0 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- (*state)[n.Properties.Id] = self
-
@@ -297 +307 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
- v.Handler(n, state)
+ v.Handler(n)
@@ -303,0 +314,60 @@ func (c *CSS) ComputeNodeStyle(n *element.Node, state *map[string]element.State)
+func InitNode(n *element.Node, c CSS) *element.Node {
+ n.Style = c.GetStyles(*n)
+ border, err := CompleteBorder(n.Style)
+ if err == nil {
+ n.Properties.Border = border
+ }
+
+ fs, _ := utils.ConvertToPixels(n.Style["font-size"], n.Parent.Properties.EM, n.Parent.Properties.Computed["width"])
+ n.Properties.EM = fs
+
+ width, _ := utils.ConvertToPixels(n.Style["width"], n.Properties.EM, n.Parent.Properties.Computed["width"])
+ if n.Style["min-width"] != "" {
+ minWidth, _ := utils.ConvertToPixels(n.Style["min-width"], n.Properties.EM, n.Parent.Properties.Computed["width"])
+ width = utils.Max(width, minWidth)
+ }
+
+ if n.Style["max-width"] != "" {
+ maxWidth, _ := utils.ConvertToPixels(n.Style["max-width"], n.Properties.EM, n.Parent.Properties.Computed["width"])
+ width = utils.Min(width, maxWidth)
+ }
+
+ height, _ := utils.ConvertToPixels(n.Style["height"], n.Properties.EM, n.Parent.Properties.Computed["height"])
+ if n.Style["min-height"] != "" {
+ minHeight, _ := utils.ConvertToPixels(n.Style["min-height"], n.Properties.EM, n.Parent.Properties.Computed["height"])
+ height = utils.Max(height, minHeight)
+ }
+
+ if n.Style["max-height"] != "" {
+ maxHeight, _ := utils.ConvertToPixels(n.Style["max-height"], n.Properties.EM, n.Parent.Properties.Computed["height"])
+ height = utils.Min(height, maxHeight)
+ }
+
+ n.Properties.Computed["width"] = width
+ n.Properties.Computed["height"] = height
+
+ bold, italic := false, false
+
+ if n.Style["font-weight"] == "bold" {
+ bold = true
+ }
+
+ if n.Style["font-style"] == "italic" {
+ italic = true
+ }
+
+ f, _ := font.LoadFont(n.Style["font-family"], int(n.Properties.EM), bold, italic)
+ letterSpacing, _ := utils.ConvertToPixels(n.Style["letter-spacing"], n.Properties.EM, width)
+ wordSpacing, _ := utils.ConvertToPixels(n.Style["word-spacing"], n.Properties.EM, width)
+ lineHeight, _ := utils.ConvertToPixels(n.Style["line-height"], n.Properties.EM, width)
+ if lineHeight == 0 {
+ lineHeight = n.Properties.EM + 3
+ }
+
+ n.Properties.Text.LineHeight = int(lineHeight)
+ n.Properties.Text.Font = f
+ n.Properties.Text.WordSpacing = int(wordSpacing)
+ n.Properties.Text.LetterSpacing = int(letterSpacing)
+ return n
+}
+
@@ -347,4 +417,3 @@ func CompleteBorder(cssProperties map[string]string) (element.Border, error) {
-func genTextNode(n *element.Node, width, height *float32, p element.MarginPadding, state *map[string]element.State) {
- s := *state
- self := s[n.Properties.Id]
- parent := s[n.Parent.Properties.Id]
+func flatten(n element.Node) []element.Node {
+ var nodes []element.Node
+ nodes = append(nodes, n)
@@ -352,20 +421,6 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- bold, italic := false, false
-
- if n.Style["font-weight"] == "bold" {
- bold = true
- }
-
- if n.Style["font-style"] == "italic" {
- italic = true
- }
-
- if self.Text.Font == nil {
- f, _ := font.LoadFont(n.Style["font-family"], int(self.EM), bold, italic)
- self.Text.Font = f
- }
-
- letterSpacing, _ := utils.ConvertToPixels(n.Style["letter-spacing"], self.EM, *width)
- wordSpacing, _ := utils.ConvertToPixels(n.Style["word-spacing"], self.EM, *width)
- lineHeight, _ := utils.ConvertToPixels(n.Style["line-height"], self.EM, *width)
- if lineHeight == 0 {
- lineHeight = self.EM + 3
+ children := n.Children
+ if len(children) > 0 {
+ for _, ch := range children {
+ chNodes := flatten(ch)
+ nodes = append(nodes, chNodes...)
+ }
@@ -372,0 +428,2 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
+ return nodes
+}
@@ -374,3 +431 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- self.Text.LineHeight = int(lineHeight)
- self.Text.WordSpacing = int(wordSpacing)
- self.Text.LetterSpacing = int(letterSpacing)
+func genTextNode(n *element.Node, width, height *float32, p utils.MarginPadding) {
@@ -386,0 +442,3 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
+ letterSpacing, _ := utils.ConvertToPixels(n.Style["letter-spacing"], n.Properties.EM, *width)
+ wordSpacing, _ := utils.ConvertToPixels(n.Style["word-spacing"], n.Properties.EM, *width)
+
@@ -392 +450 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- dt, _ = utils.ConvertToPixels(n.Style["text-decoration-thickness"], self.EM, *width)
+ dt, _ = utils.ConvertToPixels(n.Style["text-decoration-thickness"], n.Properties.EM, *width)
@@ -397,13 +455,12 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- self.Text.Color = col
- self.Text.Align = n.Style["text-align"]
- self.Text.WordBreak = wb
- self.Text.WordSpacing = int(wordSpacing)
- self.Text.LetterSpacing = int(letterSpacing)
- self.Text.WhiteSpace = n.Style["white-space"]
- self.Text.DecorationThickness = int(dt)
- self.Text.Overlined = n.Style["text-decoration"] == "overline"
- self.Text.Underlined = n.Style["text-decoration"] == "underline"
- self.Text.LineThrough = n.Style["text-decoration"] == "linethrough"
- self.Text.EM = int(self.EM)
- self.Text.Width = int(parent.Width)
- self.Text.Text = n.InnerText
+ n.Properties.Text.Color = col
+ n.Properties.Text.Align = n.Style["text-align"]
+ n.Properties.Text.WordBreak = wb
+ n.Properties.Text.WordSpacing = int(wordSpacing)
+ n.Properties.Text.LetterSpacing = int(letterSpacing)
+ n.Properties.Text.WhiteSpace = n.Style["white-space"]
+ n.Properties.Text.DecorationThickness = int(dt)
+ n.Properties.Text.Overlined = n.Style["text-decoration"] == "overline"
+ n.Properties.Text.Underlined = n.Style["text-decoration"] == "underline"
+ n.Properties.Text.LineThrough = n.Style["text-decoration"] == "linethrough"
+ n.Properties.Text.EM = int(n.Properties.EM)
+ n.Properties.Text.Width = int(n.Parent.Properties.Computed["width"])
@@ -412 +469 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- self.Text.WordSpacing = font.MeasureSpace(&self.Text)
+ n.Properties.Text.WordSpacing = font.MeasureSpace(&n.Properties.Text)
@@ -414,2 +471,2 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- if parent.Width != 0 && n.Style["display"] != "inline" && n.Style["width"] == "" {
- *width = (parent.Width - p.Right) - p.Left
+ if n.Parent.Properties.Computed["width"] != 0 && n.Style["display"] != "inline" && n.Style["width"] == "" {
+ *width = (n.Parent.Properties.Computed["width"] - p.Right) - p.Left
@@ -417 +474 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- *width = utils.Max(*width, float32(font.MeasureLongest(&self)))
+ *width = utils.Max(*width, float32(font.MeasureLongest(n)))
@@ -419 +476 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- *width, _ = utils.ConvertToPixels(n.Style["width"], self.EM, parent.Width)
+ *width, _ = utils.ConvertToPixels(n.Style["width"], n.Properties.EM, n.Parent.Properties.Computed["width"])
@@ -422,2 +479,2 @@ func genTextNode(n *element.Node, width, height *float32, p element.MarginPaddin
- self.Text.Width = int(*width)
- h := font.Render(&self)
+ n.Properties.Text.Width = int(*width)
+ h := font.Render(n)