fix html to png
This commit is contained in:
141
canvas.go
Normal file
141
canvas.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package libgofunc
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/fogleman/gg"
|
||||
"golang.org/x/image/font"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
// -------------------- STYLE --------------------
|
||||
type Style struct {
|
||||
PaddingLeft float64
|
||||
PaddingRight float64
|
||||
PaddingTop float64
|
||||
PaddingBottom float64
|
||||
FontSize float64
|
||||
Width float64
|
||||
Height float64
|
||||
TextAlign string
|
||||
VerticalAlign string
|
||||
Border float64
|
||||
}
|
||||
|
||||
func parseStyle(styleStr string) Style {
|
||||
style := Style{
|
||||
FontSize: 16,
|
||||
TextAlign: "left",
|
||||
VerticalAlign: "top",
|
||||
}
|
||||
|
||||
parts := strings.Split(styleStr, ";")
|
||||
for _, p := range parts {
|
||||
kv := strings.SplitN(strings.TrimSpace(p), ":", 2)
|
||||
if len(kv) != 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(kv[0])
|
||||
val := strings.TrimSpace(kv[1])
|
||||
|
||||
switch key {
|
||||
case "padding":
|
||||
v := parsePx(val)
|
||||
style.PaddingLeft, style.PaddingRight, style.PaddingTop, style.PaddingBottom = v, v, v, v
|
||||
case "padding-left":
|
||||
v := parsePx(val)
|
||||
style.PaddingLeft = v
|
||||
case "padding-right":
|
||||
v := parsePx(val)
|
||||
style.PaddingRight = v
|
||||
case "padding-top":
|
||||
v := parsePx(val)
|
||||
style.PaddingTop = v
|
||||
case "padding-bottom":
|
||||
v := parsePx(val)
|
||||
style.PaddingBottom = v
|
||||
case "font-size":
|
||||
style.FontSize = parsePx(val)
|
||||
case "width":
|
||||
style.Width = parsePx(val)
|
||||
case "height":
|
||||
style.Height = parsePx(val)
|
||||
case "text-align":
|
||||
style.TextAlign = val
|
||||
case "vertical-align":
|
||||
style.VerticalAlign = val
|
||||
case "border":
|
||||
style.Border = parsePx(val)
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
func parsePx(v string) float64 {
|
||||
v = strings.ReplaceAll(v, "px", "")
|
||||
f, _ := strconv.ParseFloat(v, 64)
|
||||
return f
|
||||
}
|
||||
|
||||
// -------------------- NODE --------------------
|
||||
type Node struct {
|
||||
Tag string
|
||||
Text string
|
||||
Attr map[string]string
|
||||
Style Style
|
||||
Children []*Node
|
||||
}
|
||||
|
||||
func (n Node) getSrc() string {
|
||||
for k, v := range n.Attr {
|
||||
if k == "src" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (n Node) getHeight() int {
|
||||
return int(n.Style.Height)
|
||||
}
|
||||
|
||||
func BuildTree(n *html.Node, canvasWidth int, dc *gg.Context, face *font.Face) (*Node, int) {
|
||||
if n.Type != html.ElementNode {
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
text := ""
|
||||
if n.Data == "h1" || n.Data == "h2" || n.Data == "h3" ||
|
||||
n.Data == "p" || n.Data == "td" || n.Data == "th" ||
|
||||
n.Type == html.TextNode {
|
||||
text = getText(n)
|
||||
}
|
||||
|
||||
node := &Node{
|
||||
Tag: n.Data,
|
||||
Text: text,
|
||||
Attr: map[string]string{},
|
||||
}
|
||||
|
||||
for _, a := range n.Attr {
|
||||
node.Attr[a.Key] = a.Val
|
||||
}
|
||||
|
||||
if s, ok := node.Attr["style"]; ok {
|
||||
node.Style = parseStyle(s)
|
||||
}
|
||||
xPadding := node.Style.PaddingLeft + node.Style.PaddingRight
|
||||
yPadding := node.Style.PaddingTop + node.Style.PaddingBottom
|
||||
fontSize := node.Style.FontSize
|
||||
h := nodeHeight(n, dc, canvasWidth, int(xPadding), int(yPadding),
|
||||
face, fontSize, node.getHeight())
|
||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||
child, ch := BuildTree(c, canvasWidth, dc, face)
|
||||
if child != nil {
|
||||
node.Children = append(node.Children, child)
|
||||
}
|
||||
h += ch
|
||||
}
|
||||
return node, h
|
||||
}
|
||||
Reference in New Issue
Block a user