126 lines
5.1 KiB
Go
126 lines
5.1 KiB
Go
package svg
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"regexp"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
var transitLegendSwatchPattern = regexp.MustCompile(`<rect [^>]*width="18" height="9"[^>]*fill-opacity="([0-9.]+)"`)
|
||
|
|
|
||
|
|
type transitOverlapCase struct {
|
||
|
|
name string
|
||
|
|
render func(width, height int) (string, bool)
|
||
|
|
}
|
||
|
|
|
||
|
|
func transitOverlapCases() []transitOverlapCase {
|
||
|
|
partial := time.Date(1937, time.May, 11, 0, 0, 0, 0, time.UTC)
|
||
|
|
ordinary := time.Date(2012, time.June, 6, 0, 0, 0, 0, time.UTC)
|
||
|
|
return []transitOverlapCase{
|
||
|
|
{"local-partial-zh", func(width, height int) (string, bool) {
|
||
|
|
return TransitLocalSVG(TransitMercury, partial, 0, -60, 0, TransitLocalSVGOptions{Width: width, Height: height})
|
||
|
|
}},
|
||
|
|
{"local-partial-en", func(width, height int) (string, bool) {
|
||
|
|
return TransitLocalSVG(TransitMercury, partial, 0, -60, 0, TransitLocalSVGOptions{Width: width, Height: height, Language: "en"})
|
||
|
|
}},
|
||
|
|
{"local-full-zh", func(width, height int) (string, bool) {
|
||
|
|
return TransitLocalSVG(TransitVenus, ordinary, 116.4, 39.9, 0, TransitLocalSVGOptions{Width: width, Height: height})
|
||
|
|
}},
|
||
|
|
{"local-full-en", func(width, height int) (string, bool) {
|
||
|
|
return TransitLocalSVG(TransitVenus, ordinary, 116.4, 39.9, 0, TransitLocalSVGOptions{Width: width, Height: height, Language: "en"})
|
||
|
|
}},
|
||
|
|
{"map-partial", func(width, height int) (string, bool) {
|
||
|
|
return TransitMapSVG(TransitMercury, partial, TransitMapSVGOptions{Width: width, Height: height, Isochrones: TransitIsochroneAll})
|
||
|
|
}},
|
||
|
|
{"map-partial-orthographic", func(width, height int) (string, bool) {
|
||
|
|
return TransitMapSVG(TransitMercury, partial, TransitMapSVGOptions{
|
||
|
|
Width: width, Height: height, Isochrones: TransitIsochroneAll, Projection: EclipseMapProjectionOrthographic,
|
||
|
|
})
|
||
|
|
}},
|
||
|
|
{"map-ordinary", func(width, height int) (string, bool) {
|
||
|
|
return TransitMapSVG(TransitVenus, ordinary, TransitMapSVGOptions{Width: width, Height: height, Isochrones: TransitIsochroneAll})
|
||
|
|
}},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 凌日图与日月食图同一口径:任意两个尺寸下返回的图都必须 0 文字压叠。
|
||
|
|
func TestTransitChartTextOverlapMatrix(t *testing.T) {
|
||
|
|
for _, size := range [][2]int{{640, 420}, {640, 480}, {800, 600}, {960, 640}, {960, 680}, {1200, 800}} {
|
||
|
|
for _, test := range transitOverlapCases() {
|
||
|
|
name := fmt.Sprintf("%s/%dx%d", test.name, size[0], size[1])
|
||
|
|
document, ok := test.render(size[0], size[1])
|
||
|
|
if !ok {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
assertNoTextOverlap(t, name, document)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
// 文档下限尺寸必须继续出图,拒绝只允许出现在真放不下的画布上。
|
||
|
|
if _, ok := TransitLocalSVG(TransitMercury, time.Date(1937, time.May, 11, 0, 0, 0, 0, time.UTC), 0, -60, 0,
|
||
|
|
TransitLocalSVGOptions{Width: 640, Height: 480}); !ok {
|
||
|
|
t.Error("documented 640x480 local transit canvas was rejected")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 地心无接触的可见区填充必须落在 data-source 词表内,消费方才能判断该层来源。
|
||
|
|
func TestTransitPartialRegionsUseDocumentedDataSource(t *testing.T) {
|
||
|
|
chart, ok := TransitMapSVG(TransitMercury, time.Date(1937, time.May, 11, 0, 0, 0, 0, time.UTC), TransitMapSVGOptions{})
|
||
|
|
if !ok {
|
||
|
|
t.Fatal("partial transit render failed")
|
||
|
|
}
|
||
|
|
if !strings.Contains(chart, `data-source="`+eclipseMapSourceTransitPartialVisibility+`"`) {
|
||
|
|
t.Fatalf("partial regions carry no documented data-source marker")
|
||
|
|
}
|
||
|
|
for _, match := range eclipseMapDataSourcePattern.FindAllStringSubmatch(chart, -1) {
|
||
|
|
known := false
|
||
|
|
for _, source := range eclipseMapDataSources {
|
||
|
|
known = known || source == match[1]
|
||
|
|
}
|
||
|
|
if !known {
|
||
|
|
t.Fatalf("undocumented data-source %q", match[1])
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 图例色块画在白底上取月食图同值;部分凌日单块可见区比普通分区更浓。
|
||
|
|
func TestTransitMapFillOpacities(t *testing.T) {
|
||
|
|
for _, test := range []struct {
|
||
|
|
planet TransitPlanet
|
||
|
|
date time.Time
|
||
|
|
pattern *regexp.Regexp
|
||
|
|
region float64
|
||
|
|
}{
|
||
|
|
{TransitVenus, time.Date(2012, time.June, 6, 0, 0, 0, 0, time.UTC),
|
||
|
|
regexp.MustCompile(`class="transit-[a-z-]+-region"[^>]*fill-opacity="([0-9.]+)"`), transitMapRegionFillOpacity},
|
||
|
|
{TransitMercury, time.Date(1937, time.May, 11, 0, 0, 0, 0, time.UTC),
|
||
|
|
regexp.MustCompile(`class="transit-partial-region"[^>]*fill-opacity="([0-9.]+)"`), transitMapPartialFillOpacity},
|
||
|
|
} {
|
||
|
|
chart, ok := TransitMapSVG(test.planet, test.date, TransitMapSVGOptions{})
|
||
|
|
if !ok {
|
||
|
|
t.Fatalf("%v: render failed", test.date)
|
||
|
|
}
|
||
|
|
regions := test.pattern.FindAllStringSubmatch(chart, -1)
|
||
|
|
if len(regions) == 0 {
|
||
|
|
t.Fatalf("%v: no region fill found", test.date)
|
||
|
|
}
|
||
|
|
for _, match := range regions {
|
||
|
|
if match[1] != fmt.Sprintf("%.2f", test.region) {
|
||
|
|
t.Fatalf("%v: region fill-opacity %s, want %.2f", test.date, match[1], test.region)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
legends := transitLegendSwatchPattern.FindAllStringSubmatch(chart, -1)
|
||
|
|
if len(legends) == 0 {
|
||
|
|
t.Fatalf("%v: no legend swatch found", test.date)
|
||
|
|
}
|
||
|
|
for _, match := range legends {
|
||
|
|
if match[1] != fmt.Sprintf("%.2f", transitMapLegendFillOpacity) {
|
||
|
|
t.Fatalf("%v: legend fill-opacity %s, want %.2f", test.date, match[1], transitMapLegendFillOpacity)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if transitMapPartialFillOpacity <= transitMapRegionFillOpacity {
|
||
|
|
t.Fatal("partial-transit footprint must be denser than ordinary regions")
|
||
|
|
}
|
||
|
|
}
|