gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
74.62k stars 7.45k forks source link

Support CJK in images.Text, add width and height as optional args #11364

Open naa0yama opened 1 year ago

naa0yama commented 1 year ago

When I started using Hugo, I was really drawn to the "images.Text" feature. I'm trying to use this to generate images for the Open Graph Protocol.

Since it does not support CJK, it is in a state where it is not wrapped as shown below.

{{- $font := resources.Get "/fonts/NotoSansJP-Bold.ttf" -}}
{{- $img_base := resources.Get "/img/ogp.png" -}}
{{- $img_base = $img_base.Filter (images.Text "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみぬめもあいうえおかきくけこさしすせそたちつてとなにぬねの" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "x" 130
            "y" 220
            "font" $font
        )
    )
-}}

ogp_hufdd91d49eff6d1dff05547c7d4a76f06_74228_59b8087107427e41d2c791161541b873

Workaround

As a workaround, it can be handled by separating with spaces at moderate intervals, but I thought it would be easier to use if you could define a text area like a CSS margin. Could you consider adding it as a feature?

{{- $img_base = $img_base.Filter (images.Text "あいうえおかきくけこさしすせそ たちつてとなにぬねのはひふへほ まみぬめもあいうえおかきくけ こさしすせそたちつてとなにぬねの" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "x" 130
            "y" 220
            "font" $font
        )
    )
-}}

ogp_hufdd91d49eff6d1dff05547c7d4a76f06_74228_490208ae06a351d5c4cd8b1ac2e294fb

bep commented 1 year ago

Could you consider adding it as a feature?

Yes, I can see how that would be useful (even for non CJK languages), but I'm not totally sure how the API would look like.

naa0yama commented 1 year ago

Thank you for having interest.

  • I guess a width (of text block, in pixels) would make sense.

My first thought was to fit the page title in the blue border of the image. Therefore, I decided to output a character string in Font size (size: 60), check the number of characters that fit, and insert a space there to make a line break. In order to make this mechanical, I thought that if the margins on the four sides could be defined, it would be possible to calculate from the font size, which is the reason why I made the proposal.

  • But how do we break words?

Japanese is very difficult, so even Japanese people have different opinions on where to cut phrases and words (laughs). I don't think it's worth the cost to do it with Hugo, so I think the following is fine.

The projects below may be helpful. I initially thought about using it, but it seemed incompatible with the environment I was using, so I wanted to use Hugo's functions. Ladicle/tcardgen: Generate a TwitterCard(OGP) image for your Hugo posts.

In the case of CJK, this project seems to be output as follows, and it seems that Japanese clauses are not conscious

bep commented 1 year ago

In order to make this mechanical, I thought that if the margins on the four sides could be defined, it would be possible to calculate from the font size, which is the reason why I made the proposal.

Yea, we could do something like that.

I guess the left/top margin is somehow covered by the current x/y parameters.

What if we make it top, right bottom, left?

And retire/alias x/y.

naa0yama commented 1 year ago

Plan1

I thought about several patterns, but I felt that the optimum was different depending on the person. If you want to think about the design and put it there like me, you can substitute "x,y" of "images.Text" for the upper left specification. And if you can define the lower right coordinates, it seems that you can define the square (gray part) of the text box. I'm excited that I can write like this when writing in config.yaml

# config.yaml
params:
  opengraph:
    x: 120 # images.Text x
    y: 240 # images.Text y
    bottom_right:
      x: 1160
      y: 590

ogp

Plan2

On the other hand, while drawing a diagram, I thought that it might be easier to use if the width and height were input. The reason for calculating and using the lower right coordinate is that the size of the image you want to use "images.Text" must be the same. In this case, simply control the width so that the characters do not exceed the x-coordinate, and the height is the same. I felt that it was intuitive and easy to understand even if it became an option of "images.Text".

{{- $img_base = $img_base.Filter (images.Text "あいうえおかき…" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "x" 120
            "y" 240
            "width" 1040
            "height" 350
            "font" $font
        )
    )
-}}

Therefore, I personally think that Plan2 may be more beneficial for those who want to use it in the future, so how about this?

bep commented 1 year ago

I like plan 2, easy to understand.

hugo-sid commented 11 months ago

It will be nice, if letterspacing option can be introduced.

If introduced, the modified plan 2 will look like this:

{{- $img_base = $img_base.Filter (images.Text "あいうえおかき…" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "letterspacing" 1
            "x" 120
            "y" 240
            "width" 1040
            "height" 350
            "font" $font
        )
    )
-}}
naa0yama commented 11 months ago

letter-spacing is a nice feature. I did not know this CSS property.

It might be useful if some users want to have equally spaced letters in width and height boxes.