package render
import (
"encoding/binary"
"fmt"
"math"
"strings"
)
const canonicalToPDF = 72.0 / 300.0 // 0.24
// PageSizePt returns the page dimensions in PDF points (72 DPI).
func PageSizePt(pageSize string) (float64, float64) {
switch pageSize {
case "LARGE":
return 3300 * canonicalToPDF, 5100 * canonicalToPDF // 792 x 1224
default: // REGULAR
return 2550 * canonicalToPDF, 3300 * canonicalToPDF // 612 x 792
}
}
type Stroke struct {
PenSize float32
Color int32
Style string
PointData []byte
StrokeOrder int
}
// RenderSVG renders a page's strokes as an SVG document.
func RenderSVG(pageSize string, strokes []Stroke) string {
w, h := PageSizePt(pageSize)
var b strings.Builder
fmt.Fprintf(&b, `")
return b.String()
}
func renderArrowHeads(x1, y1, x2, y2 float64, style string, penW float64, color string) string {
arrowLen := 40.0 * canonicalToPDF
arrowAngle := 25.0 * math.Pi / 180.0
dx := x2 - x1
dy := y2 - y1
angle := math.Atan2(dy, dx)
var b strings.Builder
attrs := fmt.Sprintf(`stroke="%s" stroke-width="%.2f" stroke-linecap="round"`, color, penW)
// End arrow
ax1 := x2 - arrowLen*math.Cos(angle-arrowAngle)
ay1 := y2 - arrowLen*math.Sin(angle-arrowAngle)
ax2 := x2 - arrowLen*math.Cos(angle+arrowAngle)
ay2 := y2 - arrowLen*math.Sin(angle+arrowAngle)
fmt.Fprintf(&b, ``, x2, y2, ax1, ay1, attrs)
b.WriteString("\n")
fmt.Fprintf(&b, ``, x2, y2, ax2, ay2, attrs)
b.WriteString("\n")
if style == "double_arrow" {
revAngle := angle + math.Pi
bx1 := x1 - arrowLen*math.Cos(revAngle-arrowAngle)
by1 := y1 - arrowLen*math.Sin(revAngle-arrowAngle)
bx2 := x1 - arrowLen*math.Cos(revAngle+arrowAngle)
by2 := y1 - arrowLen*math.Sin(revAngle+arrowAngle)
fmt.Fprintf(&b, ``, x1, y1, bx1, by1, attrs)
b.WriteString("\n")
fmt.Fprintf(&b, ``, x1, y1, bx2, by2, attrs)
b.WriteString("\n")
}
return b.String()
}
func decodePoints(data []byte) []float64 {
count := len(data) / 4
points := make([]float64, count)
for i := 0; i < count; i++ {
bits := binary.LittleEndian.Uint32(data[i*4 : (i+1)*4])
points[i] = float64(math.Float32frombits(bits))
}
return points
}
func colorToCSS(argb int32) string {
r := (argb >> 16) & 0xFF
g := (argb >> 8) & 0xFF
b := argb & 0xFF
if r == 0 && g == 0 && b == 0 {
return "black"
}
return fmt.Sprintf("rgb(%d,%d,%d)", r, g, b)
}