Skip to content

Commit

Permalink
Add custom font support to images.Text
Browse files Browse the repository at this point in the history
Fixes #9253
  • Loading branch information
bep committed Dec 7, 2021
1 parent e61cdf3 commit e71d715
Show file tree
Hide file tree
Showing 14 changed files with 56 additions and 6 deletions.
5 changes: 5 additions & 0 deletions common/hugio/readers.go
Expand Up @@ -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 {
Expand Down
16 changes: 15 additions & 1 deletion docs/content/en/functions/images/index.md
Expand Up @@ -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 %}}
Expand All @@ -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"
Expand All @@ -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 %}}
Expand Down
2 changes: 2 additions & 0 deletions resources/image_test.go
Expand Up @@ -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"}
Expand Down
19 changes: 19 additions & 0 deletions resources/images/filters.go
Expand Up @@ -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"
Expand Down Expand Up @@ -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()

}
}
}
Expand Down
14 changes: 14 additions & 0 deletions resources/images/text.go
Expand Up @@ -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"
Expand All @@ -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) {
Expand All @@ -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)
Expand Down
6 changes: 1 addition & 5 deletions resources/resource/resourcetypes.go
Expand Up @@ -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
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e71d715

Please sign in to comment.