...

Source file src/gonum.org/v1/plot/font/font_test.go

Documentation: gonum.org/v1/plot/font

     1  // Copyright ©2020 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package font_test
     6  
     7  import (
     8  	"errors"
     9  	"testing"
    10  
    11  	stdfnt "golang.org/x/image/font"
    12  	"golang.org/x/image/font/sfnt"
    13  	"golang.org/x/image/math/fixed"
    14  	"gonum.org/v1/plot/font"
    15  	"gonum.org/v1/plot/font/liberation"
    16  )
    17  
    18  func TestFontExtends(t *testing.T) {
    19  	cache := font.NewCache(liberation.Collection())
    20  	for _, tc := range []struct {
    21  		font font.Font
    22  		want map[font.Length]font.Extents
    23  	}{
    24  		// values obtained when gonum/plot used the package
    25  		// github.com/freetype/truetype for handling fonts.
    26  		{
    27  			font: font.Font{Typeface: "Liberation", Variant: "Serif"},
    28  			want: map[font.Length]font.Extents{
    29  				10: {
    30  					Ascent:  8.9111328125,
    31  					Descent: 2.1630859375,
    32  					Height:  11.4990234375,
    33  				},
    34  				12: {
    35  					Ascent:  10.693359375,
    36  					Descent: 2.595703125,
    37  					Height:  13.798828125,
    38  				},
    39  				24: {
    40  					Ascent:  21.38671875,
    41  					Descent: 5.19140625,
    42  					Height:  27.59765625,
    43  				},
    44  			},
    45  		},
    46  		{
    47  			font: font.Font{Typeface: "Liberation", Variant: "Serif", Weight: stdfnt.WeightBold},
    48  			want: map[font.Length]font.Extents{
    49  				10: {
    50  					Ascent:  8.9111328125,
    51  					Descent: 2.1630859375,
    52  					Height:  11.4990234375,
    53  				},
    54  				12: {
    55  					Ascent:  10.693359375,
    56  					Descent: 2.595703125,
    57  					Height:  13.798828125,
    58  				},
    59  				24: {
    60  					Ascent:  21.38671875,
    61  					Descent: 5.19140625,
    62  					Height:  27.59765625,
    63  				},
    64  			},
    65  		},
    66  		{
    67  			font: font.Font{Typeface: "Liberation", Variant: "Serif", Style: stdfnt.StyleItalic},
    68  			want: map[font.Length]font.Extents{
    69  				10: {
    70  					Ascent:  8.9111328125,
    71  					Descent: 2.1630859375,
    72  					Height:  11.4990234375,
    73  				},
    74  				12: {
    75  					Ascent:  10.693359375,
    76  					Descent: 2.595703125,
    77  					Height:  13.798828125,
    78  				},
    79  				24: {
    80  					Ascent:  21.38671875,
    81  					Descent: 5.19140625,
    82  					Height:  27.59765625,
    83  				},
    84  			},
    85  		},
    86  		{
    87  			font: font.Font{Typeface: "Liberation", Variant: "Serif", Style: stdfnt.StyleItalic, Weight: stdfnt.WeightBold},
    88  			want: map[font.Length]font.Extents{
    89  				10: {
    90  					Ascent:  8.9111328125,
    91  					Descent: 2.1630859375,
    92  					Height:  11.4990234375,
    93  				},
    94  				12: {
    95  					Ascent:  10.693359375,
    96  					Descent: 2.595703125,
    97  					Height:  13.798828125,
    98  				},
    99  				24: {
   100  					Ascent:  21.38671875,
   101  					Descent: 5.19140625,
   102  					Height:  27.59765625,
   103  				},
   104  			},
   105  		},
   106  	} {
   107  		for _, size := range []font.Length{10, 12, 24} {
   108  			fnt := cache.Lookup(tc.font, size)
   109  			got := fnt.Extents()
   110  			if got, want := got, tc.want[size]; got != want {
   111  				t.Errorf(
   112  					"invalid font extents for %q, size=%v:\ngot= %#v\nwant=%#v",
   113  					tc.font.Name(), size, got, want,
   114  				)
   115  			}
   116  		}
   117  	}
   118  }
   119  
   120  func TestFontWidth(t *testing.T) {
   121  	cache := font.NewCache(liberation.Collection())
   122  	fnt := cache.Lookup(font.Font{Typeface: "Liberation", Variant: "Serif"}, 12)
   123  
   124  	for _, tc := range []struct {
   125  		txt  string
   126  		want font.Length
   127  	}{
   128  		// values obtained when gonum/plot used the package
   129  		// github.com/freetype/truetype for handling fonts.
   130  		{" ", 3},
   131  		{"i", 3.333984375},
   132  		{"q", 6},
   133  		{"A", 8.666015625},
   134  		{"F", 6.673828125},
   135  		{"T", 7.330078125},
   136  		{"V", 8.666015625},
   137  		{"Δ", 7.716796875},
   138  		{"∇", 9.333984375},
   139  		{"  ", 6},
   140  		{"AA", 17.33203125},
   141  		{"Aq", 14.666015625},
   142  		{"Fi", 10.0078125},
   143  		{"Ti", 10.2421875},
   144  		{"AV", 15.78515625},
   145  		{"A∇", 18},
   146  		{"VA", 15.78515625},
   147  		{"VΔ", 16.3828125},
   148  		{"∇Δ", 17.05078125},
   149  		{"   ", 9},
   150  		{"T T", 17.2265625},
   151  	} {
   152  		t.Run(tc.txt, func(t *testing.T) {
   153  			got := fnt.Width(tc.txt)
   154  			if got, want := got, tc.want; got != want {
   155  				t.Fatalf(
   156  					"invalid width: got=%v, want=%v",
   157  					got, want,
   158  				)
   159  			}
   160  		})
   161  	}
   162  }
   163  
   164  func TestFontKern(t *testing.T) {
   165  	cache := font.NewCache(liberation.Collection())
   166  	fnt := cache.Lookup(font.Font{Typeface: "Liberation", Variant: "Serif"}, 12)
   167  
   168  	for _, tc := range []struct {
   169  		txt  string
   170  		want fixed.Int26_6
   171  	}{
   172  		// values obtained when gonum/plot used the package
   173  		// github.com/freetype/truetype for handling fonts.
   174  		{"AV", -264},
   175  		{"A∇", 0}, // Liberation has no kerning information for greek symbols
   176  		{"AΔ", 0},
   177  		{"AA", 0},
   178  		{"VA", -264},
   179  		{"∇A", 0}, // Liberation has no kerning information for greek symbols
   180  		{"∇Δ", 0}, // Liberation has no kerning information for greek symbols
   181  	} {
   182  		t.Run(tc.txt, func(t *testing.T) {
   183  			var (
   184  				t0 = rune(tc.txt[0])
   185  				t1 = rune(tc.txt[1])
   186  
   187  				buf  sfnt.Buffer
   188  				ppem = fixed.Int26_6(fnt.Face.UnitsPerEm())
   189  			)
   190  
   191  			i0, err := fnt.Face.GlyphIndex(&buf, t0)
   192  			if err != nil {
   193  				t.Fatalf("could not find glyph %q: %+v", t0, err)
   194  			}
   195  			i1, err := fnt.Face.GlyphIndex(&buf, t1)
   196  			if err != nil {
   197  				t.Fatalf("could not find glyph %q: %+v", t1, err)
   198  			}
   199  			kern, err := fnt.Face.Kern(&buf, i0, i1, ppem, stdfnt.HintingNone)
   200  			switch {
   201  			case err == nil:
   202  				// ok
   203  			case errors.Is(err, sfnt.ErrNotFound):
   204  				kern = 0
   205  			default:
   206  				t.Fatalf("could not find kerning for %q/%q: %+v", t0, t1, err)
   207  			}
   208  
   209  			if got, want := kern, tc.want; got != want {
   210  				t.Fatalf("invalid kerning: got=%v, want=%v", got, want)
   211  			}
   212  		})
   213  	}
   214  }
   215  
   216  func TestFontName(t *testing.T) {
   217  	for _, tc := range []struct {
   218  		font *font.Font
   219  		want string
   220  	}{
   221  		{
   222  			font: &font.Font{
   223  				Typeface: "Liberation",
   224  				Variant:  "Sans",
   225  				Style:    stdfnt.StyleNormal,
   226  				Weight:   stdfnt.WeightNormal,
   227  			},
   228  			want: "LiberationSans-Regular",
   229  		},
   230  		{
   231  			font: &font.Font{
   232  				Typeface: "Liberation",
   233  				Variant:  "Sans",
   234  				Style:    stdfnt.StyleItalic,
   235  				Weight:   stdfnt.WeightNormal,
   236  			},
   237  			want: "LiberationSans-Italic",
   238  		},
   239  		{
   240  			font: &font.Font{
   241  				Typeface: "Liberation",
   242  				Variant:  "Sans",
   243  				Style:    stdfnt.StyleNormal,
   244  				Weight:   stdfnt.WeightBold,
   245  			},
   246  			want: "LiberationSans-Bold",
   247  		},
   248  		{
   249  			font: &font.Font{
   250  				Typeface: "Liberation",
   251  				Variant:  "Sans",
   252  				Style:    stdfnt.StyleItalic,
   253  				Weight:   stdfnt.WeightBold,
   254  			},
   255  			want: "LiberationSans-BoldItalic",
   256  		},
   257  		{
   258  			font: &font.Font{
   259  				Typeface: "Liberation",
   260  				Variant:  "Mono",
   261  				Style:    stdfnt.StyleNormal,
   262  				Weight:   stdfnt.WeightNormal,
   263  			},
   264  			want: "LiberationMono-Regular",
   265  		},
   266  		{
   267  			font: &font.Font{
   268  				Typeface: "Liberation",
   269  				Variant:  "Mono",
   270  				Style:    stdfnt.StyleItalic,
   271  				Weight:   stdfnt.WeightNormal,
   272  			},
   273  			want: "LiberationMono-Italic",
   274  		},
   275  		{
   276  			font: &font.Font{
   277  				Typeface: "Liberation",
   278  				Variant:  "Mono",
   279  				Style:    stdfnt.StyleNormal,
   280  				Weight:   stdfnt.WeightBold,
   281  			},
   282  			want: "LiberationMono-Bold",
   283  		},
   284  		{
   285  			font: &font.Font{
   286  				Typeface: "Liberation",
   287  				Variant:  "Mono",
   288  				Style:    stdfnt.StyleItalic,
   289  				Weight:   stdfnt.WeightBold,
   290  			},
   291  			want: "LiberationMono-BoldItalic",
   292  		},
   293  	} {
   294  		got := tc.font.Name()
   295  		if got != tc.want {
   296  			t.Errorf("invalid name: got=%q, want=%q", got, tc.want)
   297  		}
   298  	}
   299  }
   300  

View as plain text