Files
astro/moon/svg/footer_margin_contract_test.go
T

108 lines
3.9 KiB
Go
Raw Normal View History

package svg
import (
"fmt"
"strings"
"testing"
"time"
"b612.me/astro/internal/svgchart"
)
// 页脚排版契约:任何文字的下沿都要离画布底边留出余量,避免末行贴边或被裁掉。
const occultationChartBottomMarginMinimum = 6.0
func occultationBottomMarginViolations(t *testing.T, diagram string, height int) []string {
t.Helper()
violations := []string{}
for _, text := range occultationSVGTexts(t, diagram) {
if text.value == "" {
continue
}
_, below := svgchart.EstimatedTextExtents(text.fontSize)
if margin := float64(height) - (text.y + below); margin < occultationChartBottomMarginMinimum {
violations = append(violations, fmt.Sprintf("%q 距底边 %.2f px(下限 %.1f)", text.value, margin, occultationChartBottomMarginMinimum))
}
}
return violations
}
func TestOccultationChartsKeepBottomMargin(t *testing.T) {
long := footerFitLongText("margin ")
starPath := occultationTestStarPath(t)
planetPath := occultationTestSaturnPath(t)
cases := []struct {
name string
height int
document string
}{}
add := func(name string, height int, document string, err error) {
if err != nil {
t.Fatalf("%s: %v", name, err)
}
cases = append(cases, struct {
name string
height int
document string
}{name, height, document})
}
for _, size := range [][2]int{{640, 480}, {920, 720}} {
options := footerFitStarTexts(long)
options.Width, options.Height = size[0], size[1]
diagram, err := StarOccultationPathSVG(starPath, options)
add(fmt.Sprintf("恒星全球 %dx%d", size[0], size[1]), size[1], diagram, err)
planetOptions := PlanetOccultationSVGOptions(options)
planetDiagram, err := PlanetOccultationPathSVG(planetPath, planetOptions)
add(fmt.Sprintf("行星全球 %dx%d", size[0], size[1]), size[1], planetDiagram, err)
}
local, err := LocalStarOccultationSVG(localHR4799Occultation(t), hr4799StarCoordinate(), LocalStarOccultationSVGOptions{
Width: 640, Height: 520, Title: long, DirectionText: long, FooterNote: long,
})
add("站心恒星", 520, local, err)
localPlanet, err := LocalPlanetOccultationSVG(localSaturnOccultation(t), LocalPlanetOccultationSVGOptions{
Width: 760, Height: 600, Title: long, DirectionText: long, FooterNote: long,
})
add("站心行星", 600, localPlanet, err)
detailed, err := StarOccultationDetailedSVG(starPath, hr4799StarCoordinate(), OccultationDetailedSVGOptions{
Width: 700, Height: 990, Title: long, FooterNote: long,
})
add("恒星详图", 990, detailed, err)
for _, tc := range cases {
if violations := occultationBottomMarginViolations(t, tc.document, tc.height); len(violations) > 0 {
t.Errorf("%s:%d 行文字贴到画布底边,首条 %s", tc.name, len(violations), violations[0])
}
}
}
// 页脚时标声明契约:超长自定义说明可以吃掉说明文字,但不能吃掉时标声明。
func TestOccultationChartsKeepTimeScaleDeclaration(t *testing.T) {
long := footerFitLongText("scale ")
cst := time.FixedZone("CST", 8*3600)
starPath := occultationTestStarPath(t)
planetPath := occultationTestSaturnPath(t)
options := footerFitStarTexts(long)
options.Width, options.Height = 920, 720
options.Location = cst
global, err := StarOccultationPathSVG(starPath, options)
if err != nil {
t.Fatalf("恒星全球:%v", err)
}
planetOptions := PlanetOccultationSVGOptions(options)
planet, err := PlanetOccultationPathSVG(planetPath, planetOptions)
if err != nil {
t.Fatalf("行星全球:%v", err)
}
local, err := LocalStarOccultationSVG(localHR4799Occultation(t), hr4799StarCoordinate(), LocalStarOccultationSVGOptions{
Width: 920, Height: 720, Location: cst, FooterNote: long,
})
if err != nil {
t.Fatalf("站心恒星:%v", err)
}
for name, document := range map[string]string{"恒星全球": global, "行星全球": planet, "站心恒星": local} {
if !strings.Contains(document, "显示时区") && !strings.Contains(document, "图中时刻为 UTC") {
t.Errorf("%s:超长说明把时标声明挤掉了", name)
}
}
}