diff options
author | Bjørn Erik Pedersen <[email protected]> | 2021-12-07 12:49:53 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2021-12-07 16:53:02 +0100 |
commit | e71d715b9b0c55aea7ef4fc88642eecd6e7b58c3 (patch) | |
tree | 1cd92998eb1c72ea11d1764025f4414787b90fa7 | |
parent | e61cdf335f9d102621c37d0d366da61afa698c99 (diff) | |
download | hugo-e71d715b9b0c55aea7ef4fc88642eecd6e7b58c3.tar.gz hugo-e71d715b9b0c55aea7ef4fc88642eecd6e7b58c3.zip |
Add custom font support to images.Text
Fixes #9253
14 files changed, 56 insertions, 6 deletions
diff --git a/common/hugio/readers.go b/common/hugio/readers.go index c93e05e86..60bd97992 100644 --- a/common/hugio/readers.go +++ b/common/hugio/readers.go @@ -31,6 +31,11 @@ type ReadSeekCloser interface { io.Closer } +// ReadSeekCloserProvider provides a ReadSeekCloser. +type ReadSeekCloserProvider interface { + ReadSeekCloser() (ReadSeekCloser, error) +} + // ReadSeekerNoOpCloser implements ReadSeekCloser by doing nothing in Close. // TODO(bep) rename this and similar to ReadSeekerNopCloser, naming used in stdlib, which kind of makes sense. type ReadSeekerNoOpCloser struct { diff --git a/docs/content/en/functions/images/index.md b/docs/content/en/functions/images/index.md index 274072dba..1cf69ee78 100644 --- a/docs/content/en/functions/images/index.md +++ b/docs/content/en/functions/images/index.md @@ -42,6 +42,8 @@ The above will overlay `$logo` in the upper left corner of `$img` (at position ` ### Text +{{< new-in "0.90.0" >}} + Using the `Text` filter, you can add text to an image. {{% funcsig %}} @@ -50,7 +52,7 @@ images.Text TEXT DICT) The following example will add the text `Hugo rocks!` to the image with the specified color, size and position. -``` +```go-html-template {{ $img := resources.Get "/images/background.png"}} {{ $img = $img.Filter (images.Text "Hugo rocks!" (dict "color" "#ffffff" @@ -61,6 +63,18 @@ The following example will add the text `Hugo rocks!` to the image with the spec ))}} ``` +You can load a custom font if needed. Load the font as a Hugo `Resource` and set it as an option: + +```go-html-template + +{{ $font := resources.Get "https://github.com/google/fonts/raw/main/apache/roboto/static/Roboto-Black.ttf" }} +{{ $img := resources.Get "/images/background.png"}} +{{ $img = $img.Filter (images.Text "Hugo rocks!" (dict + "font" $font +))}} +``` + + ### Brightness {{% funcsig %}} diff --git a/resources/image_test.go b/resources/image_test.go index 41558a7a5..ad8c42bd7 100644 --- a/resources/image_test.go +++ b/resources/image_test.go @@ -597,6 +597,8 @@ func TestImageOperationsGolden(t *testing.T) { c := qt.New(t) c.Parallel() + // Note, if you're enabling this on a MacOS M1 (ARM) you need to run the test with GOARCH=amd64. + // GOARCH=amd64 go test -timeout 30s -run "^TestImageOperationsGolden$" ./resources -v devMode := false testImages := []string{"sunset.jpg", "gohugoio8.png", "gohugoio24.png"} diff --git a/resources/images/filters.go b/resources/images/filters.go index 63caefdd1..e166a0f9d 100644 --- a/resources/images/filters.go +++ b/resources/images/filters.go @@ -15,7 +15,11 @@ package images import ( + "fmt" + + "github.com/gohugoio/hugo/common/hugio" "github.com/gohugoio/hugo/common/maps" + "github.com/gohugoio/hugo/resources/resource" "github.com/disintegration/gift" "github.com/spf13/cast" @@ -61,6 +65,21 @@ func (*Filters) Text(text string, options ...interface{}) gift.Filter { tf.y = cast.ToInt(v) case "linespacing": tf.linespacing = cast.ToInt(v) + case "font": + fontSource, ok1 := v.(hugio.ReadSeekCloserProvider) + identifier, ok2 := v.(resource.Identifier) + + if !(ok1 && ok2) { + panic(fmt.Sprintf("invalid text font source: %T", v)) + } + + tf.fontSource = fontSource + + // The input value isn't hashable and will not make a stable key. + // Replace it with a string in the map used as basis for the + // hash string. + opt["font"] = identifier.Key() + } } } diff --git a/resources/images/text.go b/resources/images/text.go index a90f25272..cc67a5d1d 100644 --- a/resources/images/text.go +++ b/resources/images/text.go @@ -16,9 +16,11 @@ package images import ( "image" "image/draw" + "io" "strings" "github.com/disintegration/gift" + "github.com/gohugoio/hugo/common/hugio" "golang.org/x/image/font" "golang.org/x/image/font/gofont/goregular" @@ -33,6 +35,7 @@ type textFilter struct { x, y int size float64 linespacing int + fontSource hugio.ReadSeekCloserProvider } func (f textFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) { @@ -43,6 +46,17 @@ func (f textFilter) Draw(dst draw.Image, src image.Image, options *gift.Options) // Load and parse font ttf := goregular.TTF + if f.fontSource != nil { + rs, err := f.fontSource.ReadSeekCloser() + if err != nil { + panic(err) + } + defer rs.Close() + ttf, err = io.ReadAll(rs) + if err != nil { + panic(err) + } + } otf, err := opentype.Parse(ttf) if err != nil { panic(err) diff --git a/resources/resource/resourcetypes.go b/resources/resource/resourcetypes.go index 206ce8de8..8ab77e436 100644 --- a/resources/resource/resourcetypes.go +++ b/resources/resource/resourcetypes.go @@ -155,11 +155,7 @@ type OpenReadSeekCloser func() (hugio.ReadSeekCloser, error) // ReadSeekCloserResource is a Resource that supports loading its content. type ReadSeekCloserResource interface { MediaType() media.Type - ReadSeekCloserProvider -} - -type ReadSeekCloserProvider interface { - ReadSeekCloser() (hugio.ReadSeekCloser, error) + hugio.ReadSeekCloserProvider } // LengthProvider is a Resource that provides a length diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fill_gaussian_smart1_3.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fill_gaussian_smart1_3.png Binary files differindex 8dd7342ec..4ef633564 100644 --- a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fill_gaussian_smart1_3.png +++ b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fill_gaussian_smart1_3.png diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png Binary files differindex 30161204c..46fa3fd1b 100644 --- a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png +++ b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png Binary files differindex f1968edba..2fece7804 100644 --- a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png +++ b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png Binary files differindex 723e78ce1..32c5b49d8 100644 --- a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png +++ b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png Binary files differindex c1b60fa2a..174649232 100644 --- a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png +++ b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png Binary files differindex f7d0edb31..51f6cfa7e 100644 --- a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png +++ b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png Binary files differindex 789912a6d..c8f782598 100644 --- a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png +++ b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png Binary files differindex f5c9ec0d1..2def214c8 100644 --- a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png +++ b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png |