Skip to content

Commit

Permalink
fixed PNG font rendering for high DPI
Browse files Browse the repository at this point in the history
  • Loading branch information
pbnjay committed Jun 30, 2020
1 parent b108266 commit 532734b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 13 deletions.
29 changes: 24 additions & 5 deletions drawing/draw.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ package drawing

import (
"fmt"
"log"
"sort"
"strings"
"unicode"

"github.com/golang/freetype/truetype"
"github.com/joiningdata/lollipops/data"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
)

type diagram struct {
Expand Down Expand Up @@ -192,10 +196,10 @@ func (s *Settings) prepare(changelist []string, g *data.GraphicResponse) *diagra
label := ""

if swidth > 10 && s.DomainLabelStyle != "off" {
if len(r.Metadata.Description) > 1 && float64(MeasureFont(r.Metadata.Description, 12)) < (swidth-s.TextPadding) {
if len(r.Metadata.Description) > 1 && float64(s.MeasureFont(r.Metadata.Description, 12)) < (swidth-s.TextPadding) {
// we can fit the full description! nice!
label = r.Metadata.Description
} else if float64(MeasureFont(r.Text, 12)) < (swidth - s.TextPadding) {
} else if float64(s.MeasureFont(r.Text, 12)) < (swidth - s.TextPadding) {
label = r.Text
} else if s.DomainLabelStyle == "truncate" {
didOutput := false
Expand All @@ -216,7 +220,7 @@ func (s *Settings) prepare(changelist []string, g *data.GraphicResponse) *diagra
if i == 0 {
pre = ""
}
if float64(MeasureFont(pre+parts[i]+post, 12)) < (swidth - s.TextPadding) {
if float64(s.MeasureFont(pre+parts[i]+post, 12)) < (swidth - s.TextPadding) {
label = pre + parts[i] + post
didOutput = true
break
Expand All @@ -229,7 +233,7 @@ func (s *Settings) prepare(changelist []string, g *data.GraphicResponse) *diagra
sub := r.Text
for mx := len(r.Text) - 2; mx > 0; mx-- {
sub = strings.TrimFunc(r.Text[:mx], unicode.IsPunct) + ".."
if float64(MeasureFont(sub, 12)) < (swidth - s.TextPadding) {
if float64(s.MeasureFont(sub, 12)) < (swidth - s.TextPadding) {
break
}
}
Expand All @@ -246,7 +250,22 @@ func (s *Settings) prepare(changelist []string, g *data.GraphicResponse) *diagra
}

if s.legendInfo != nil {
s.GraphicHeight += float64(1+len(s.legendInfo)) * 14.0

fface := truetype.NewFace(theFont, &truetype.Options{
Size: float64(12.0),
DPI: float64(DefaultSettings.dpi),
Hinting: font.HintingFull,
})
// get font height in px
bounds, _, ok := fface.GlyphBounds('M')
if !ok {
log.Fatalf("unable to determine font bounds!")
}
// add 2px line spacing
fontH := bounds.Max.Sub(bounds.Min).Y + fixed.I(2)
s.GraphicHeight += float64(2 * fontH.Ceil())

s.GraphicHeight += float64(len(s.legendInfo)*fontH.Ceil()) * 1.2
for key, color := range s.legendInfo {
if rename, found := data.MotifNames[key]; found {
delete(s.legendInfo, key)
Expand Down
4 changes: 2 additions & 2 deletions drawing/fonts.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ func LoadFont(name, path string) error {
// MeasureFont returns the pixel width of the string s at font size sz.
// It tries to use system Arial font if possible, but falls back to a
// conservative ballpark estimate otherwise.
func MeasureFont(s string, sz int) int {
func (x *Settings) MeasureFont(s string, sz int) int {
// use actual TTF font metrics if available
if theFont != nil {
myFace := truetype.NewFace(theFont, &truetype.Options{
Size: float64(sz),
DPI: float64(DefaultSettings.dpi),
DPI: float64(x.dpi),
})
d := &font.Drawer{Face: myFace}
w := d.MeasureString(s)
Expand Down
11 changes: 6 additions & 5 deletions drawing/png.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,21 +214,22 @@ func (s *diagram) png(w io.Writer) {
}
blackFontDrawer.DrawString(spos)
}
startY += s.AxisHeight
startY += s.AxisHeight + float64(fontH.Ceil())
}

legBoxSize := float64(fontH.Ceil())
for key, colorstring := range s.legendInfo {
startY += 14.0
startY += legBoxSize * 1.2
// 15% darker than backbone (i.e. disordered color)
clr := color.RGBA{0x9E, 0xA0, 0x9A, 0xFF}
if key != data.MotifNames["disorder"] {
clr = colorFromHex(BlendColorStrings(colorstring, "#FFFFFF"))
}
drawRectWHShadow(img, 4, startY, 12, 12, clr, 2*s.dpi/72.0)
drawRectWHShadow(img, legBoxSize, startY, legBoxSize, legBoxSize, clr, 2*s.dpi/72.0)

blackFontDrawer.Dot = fixed.Point26_6{
X: fixed.I(20),
Y: fixed.I(int(startY + 12)), // 12=font height-baseline
X: fixed.I(int(legBoxSize)) + fixed.I(int(legBoxSize*1.4)),
Y: fixed.I(int(startY + legBoxSize)),
}
blackFontDrawer.DrawString(key)
}
Expand Down
2 changes: 1 addition & 1 deletion drawing/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (s *Settings) AutoWidth(g *data.GraphicResponse) float64 {
send, _ := r.End.Float64()

aaPart := (send - sstart) / aaLen
minTextWidth := float64(MeasureFont(r.Text, 12)) + (s.TextPadding * 2) + 1
minTextWidth := float64(s.MeasureFont(r.Text, 12)) + (s.TextPadding * 2) + 1

ww := minTextWidth / aaPart
if ww > w {
Expand Down

0 comments on commit 532734b

Please sign in to comment.