mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-23 22:29:59 -05:00
Merge pull request #2062 from fschade/fix-issue-1452-respect-canvas-boundaries
fix(thumbnailer): respect image boundaries and text wrappings
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
|||||||
"golang.org/x/image/math/fixed"
|
"golang.org/x/image/math/fixed"
|
||||||
|
|
||||||
"github.com/dhowden/tag"
|
"github.com/dhowden/tag"
|
||||||
|
|
||||||
thumbnailerErrors "github.com/opencloud-eu/opencloud/services/thumbnails/pkg/errors"
|
thumbnailerErrors "github.com/opencloud-eu/opencloud/services/thumbnails/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -156,15 +157,18 @@ Scan: // Label for the scanner loop, so we can break it easily
|
|||||||
if canvas.Dot.Y > maxY {
|
if canvas.Dot.Y > maxY {
|
||||||
break Scan
|
break Scan
|
||||||
}
|
}
|
||||||
drawWord(canvas, textResult.Text[initialByte:sRangeSpace], minX, maxX, height, maxY, true)
|
|
||||||
|
drawWord(canvas, textResult.Text[initialByte:sRangeSpace], minX, maxX, height, maxY)
|
||||||
initialByte = sRangeSpace
|
initialByte = sRangeSpace
|
||||||
}
|
}
|
||||||
|
|
||||||
if initialByte <= sRange.High {
|
if initialByte <= sRange.High {
|
||||||
// some bytes left to be written
|
// some bytes left to be written
|
||||||
if canvas.Dot.Y > maxY {
|
if canvas.Dot.Y > maxY {
|
||||||
break Scan
|
break Scan
|
||||||
}
|
}
|
||||||
drawWord(canvas, textResult.Text[initialByte:sRange.High+1], minX, maxX, height, maxY, len(sRange.Spaces) > 0)
|
|
||||||
|
drawWord(canvas, textResult.Text[initialByte:sRange.High+1], minX, maxX, height, maxY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,43 +239,58 @@ func extractBase64ImageFromGGP(ggp *GGPStruct) (string, error) {
|
|||||||
// need to draw the word in a new line
|
// need to draw the word in a new line
|
||||||
//
|
//
|
||||||
// Note that the word will likely start with a white space char
|
// Note that the word will likely start with a white space char
|
||||||
func drawWord(canvas *font.Drawer, word string, minX, maxX, incY, maxY fixed.Int26_6, goToNewLine bool) {
|
func drawWord(canvas *font.Drawer, word string, minX, maxX, incY, maxY fixed.Int26_6) {
|
||||||
bbox, _ := canvas.BoundString(word)
|
// calculate the actual measurement of the string at a given X position
|
||||||
if bbox.Max.X <= maxX {
|
measure := func(s string, dotX fixed.Int26_6) (min, max fixed.Int26_6) {
|
||||||
// word fits in the current line
|
bbox, _ := canvas.BoundString(s)
|
||||||
canvas.DrawString(word)
|
return dotX + bbox.Min.X, dotX + bbox.Max.X
|
||||||
} else {
|
}
|
||||||
// word doesn't fit -> retry in a new line
|
|
||||||
trimmedWord := strings.TrimSpace(word)
|
|
||||||
oldDot := canvas.Dot
|
|
||||||
|
|
||||||
canvas.Dot.X = minX
|
// first try to draw the whole word
|
||||||
canvas.Dot.Y += incY
|
absMin, absMax := measure(word, canvas.Dot.X)
|
||||||
bbox2, _ := canvas.BoundString(trimmedWord)
|
if absMin >= minX && absMax <= maxX {
|
||||||
if goToNewLine && bbox2.Max.X <= maxX {
|
canvas.DrawString(word)
|
||||||
if canvas.Dot.Y > maxY {
|
return
|
||||||
// Don't draw if we're over the Y limit
|
}
|
||||||
return
|
|
||||||
}
|
// try to draw the trimmed word in a new line
|
||||||
canvas.DrawString(trimmedWord)
|
trimmed := strings.TrimSpace(word)
|
||||||
} else {
|
oldDot := canvas.Dot
|
||||||
// word doesn't fit in a new line -> draw as many chars as possible
|
canvas.Dot.X = minX
|
||||||
canvas.Dot = oldDot
|
canvas.Dot.Y += incY
|
||||||
for _, char := range trimmedWord {
|
|
||||||
charBytes := []byte(string(char))
|
if canvas.Dot.Y <= maxY {
|
||||||
bbox3, _ := canvas.BoundBytes(charBytes)
|
tMin, tMax := measure(trimmed, canvas.Dot.X)
|
||||||
if bbox3.Max.X > maxX {
|
if tMin >= minX && tMax <= maxX {
|
||||||
canvas.Dot.X = minX
|
canvas.DrawString(trimmed)
|
||||||
canvas.Dot.Y += incY
|
return
|
||||||
if canvas.Dot.Y > maxY {
|
|
||||||
// Don't draw if we're over the Y limit
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canvas.DrawBytes(charBytes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the trimmed word is still too big, draw it char by char
|
||||||
|
canvas.Dot = oldDot
|
||||||
|
for _, char := range trimmed {
|
||||||
|
s := string(char)
|
||||||
|
_, cMax := measure(s, canvas.Dot.X)
|
||||||
|
|
||||||
|
if cMax > maxX {
|
||||||
|
canvas.Dot.X = minX
|
||||||
|
canvas.Dot.Y += incY
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop drawing if we exceed maxY
|
||||||
|
if canvas.Dot.Y > maxY {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that we don't start drawing before minX
|
||||||
|
cMin, _ := measure(s, canvas.Dot.X)
|
||||||
|
if cMin < minX {
|
||||||
|
canvas.Dot.X += minX - cMin
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.DrawString(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForType returns the converter for the specified mimeType
|
// ForType returns the converter for the specified mimeType
|
||||||
|
|||||||
Reference in New Issue
Block a user