@@ -20,6 +20,7 @@ import (
2020 "golang.org/x/image/math/fixed"
2121
2222 "github.com/dhowden/tag"
23+
2324 thumbnailerErrors "github.com/opencloud-eu/opencloud/services/thumbnails/pkg/errors"
2425)
2526
@@ -156,15 +157,18 @@ Scan: // Label for the scanner loop, so we can break it easily
156157 if canvas .Dot .Y > maxY {
157158 break Scan
158159 }
159- drawWord (canvas , textResult .Text [initialByte :sRangeSpace ], minX , maxX , height , maxY , true )
160+
161+ drawWord (canvas , textResult .Text [initialByte :sRangeSpace ], minX , maxX , height , maxY )
160162 initialByte = sRangeSpace
161163 }
164+
162165 if initialByte <= sRange .High {
163166 // some bytes left to be written
164167 if canvas .Dot .Y > maxY {
165168 break Scan
166169 }
167- drawWord (canvas , textResult .Text [initialByte :sRange .High + 1 ], minX , maxX , height , maxY , len (sRange .Spaces ) > 0 )
170+
171+ drawWord (canvas , textResult .Text [initialByte :sRange .High + 1 ], minX , maxX , height , maxY )
168172 }
169173 }
170174
@@ -235,43 +239,58 @@ func extractBase64ImageFromGGP(ggp *GGPStruct) (string, error) {
235239// need to draw the word in a new line
236240//
237241// Note that the word will likely start with a white space char
238- func drawWord (canvas * font.Drawer , word string , minX , maxX , incY , maxY fixed.Int26_6 , goToNewLine bool ) {
239- bbox , _ := canvas .BoundString (word )
240- if bbox .Max .X <= maxX {
241- // word fits in the current line
242+ func drawWord (canvas * font.Drawer , word string , minX , maxX , incY , maxY fixed.Int26_6 ) {
243+ // calculate the actual measurement of the string at a given X position
244+ measure := func (s string , dotX fixed.Int26_6 ) (min , max fixed.Int26_6 ) {
245+ bbox , _ := canvas .BoundString (s )
246+ return dotX + bbox .Min .X , dotX + bbox .Max .X
247+ }
248+
249+ // first try to draw the whole word
250+ absMin , absMax := measure (word , canvas .Dot .X )
251+ if absMin >= minX && absMax <= maxX {
242252 canvas .DrawString (word )
243- } else {
244- // word doesn't fit -> retry in a new line
245- trimmedWord := strings .TrimSpace (word )
246- oldDot := canvas .Dot
253+ return
254+ }
247255
248- canvas .Dot .X = minX
249- canvas .Dot .Y += incY
250- bbox2 , _ := canvas .BoundString (trimmedWord )
251- if goToNewLine && bbox2 .Max .X <= maxX {
252- if canvas .Dot .Y > maxY {
253- // Don't draw if we're over the Y limit
254- return
255- }
256- canvas .DrawString (trimmedWord )
257- } else {
258- // word doesn't fit in a new line -> draw as many chars as possible
259- canvas .Dot = oldDot
260- for _ , char := range trimmedWord {
261- charBytes := []byte (string (char ))
262- bbox3 , _ := canvas .BoundBytes (charBytes )
263- if bbox3 .Max .X > maxX {
264- canvas .Dot .X = minX
265- canvas .Dot .Y += incY
266- if canvas .Dot .Y > maxY {
267- // Don't draw if we're over the Y limit
268- return
269- }
270- }
271- canvas .DrawBytes (charBytes )
272- }
256+ // try to draw the trimmed word in a new line
257+ trimmed := strings .TrimSpace (word )
258+ oldDot := canvas .Dot
259+ canvas .Dot .X = minX
260+ canvas .Dot .Y += incY
261+
262+ if canvas .Dot .Y <= maxY {
263+ tMin , tMax := measure (trimmed , canvas .Dot .X )
264+ if tMin >= minX && tMax <= maxX {
265+ canvas .DrawString (trimmed )
266+ return
273267 }
274268 }
269+
270+ // if the trimmed word is still too big, draw it char by char
271+ canvas .Dot = oldDot
272+ for _ , char := range trimmed {
273+ s := string (char )
274+ _ , cMax := measure (s , canvas .Dot .X )
275+
276+ if cMax > maxX {
277+ canvas .Dot .X = minX
278+ canvas .Dot .Y += incY
279+ }
280+
281+ // stop drawing if we exceed maxY
282+ if canvas .Dot .Y > maxY {
283+ return
284+ }
285+
286+ // ensure that we don't start drawing before minX
287+ cMin , _ := measure (s , canvas .Dot .X )
288+ if cMin < minX {
289+ canvas .Dot .X += minX - cMin
290+ }
291+
292+ canvas .DrawString (s )
293+ }
275294}
276295
277296// ForType returns the converter for the specified mimeType
0 commit comments