hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit e71d715b9b0c55aea7ef4fc88642eecd6e7b58c3
parent e61cdf335f9d102621c37d0d366da61afa698c99
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Tue,  7 Dec 2021 12:49:53 +0100

Add custom font support to images.Text

Fixes #9253

Diffstat:
Mcommon/hugio/readers.go | 5+++++
Mdocs/content/en/functions/images/index.md | 16+++++++++++++++-
Mresources/image_test.go | 2++
Mresources/images/filters.go | 19+++++++++++++++++++
Mresources/images/text.go | 14++++++++++++++
Mresources/resource/resourcetypes.go | 6+-----
Mresources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_300x200_fill_gaussian_smart1_3.png | 0
Mresources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png | 0
Mresources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png | 0
Mresources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png | 0
Mresources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png | 0
Mresources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png | 0
Mresources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png | 0
Mresources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png | 0
14 files changed, 56 insertions(+), 6 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 differ.
diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_60c098f0ca6626668d9e3ad6bfb38b5b.png
Binary files differ.
diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_8166ccaf22bdabb94c9bb90bffe64133.png
Binary files differ.
diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_9a8d95423df65a9c230a4cc88056c13a.png
Binary files differ.
diff --git a/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png b/resources/testdata/golden/gohugoio24_huc57dd738f4724f4b341121e66fd85555_267952_d87fd348ad697a9b16399709441d9d56.png
Binary files differ.
diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_73c19c5f80881858a85aa23cd0ca400d.png
Binary files differ.
diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_ae631e5252bb5d7b92bc766ad1a89069.png
Binary files differ.
diff --git a/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png b/resources/testdata/golden/gohugoio8_hu7f72c00afdf7634587afaa5eff2a25b2_73538_d1bbfa2629bffb90118cacce3fcfb924.png
Binary files differ.