1package draw2dimg 2 3import ( 4 "github.com/golang/freetype/truetype" 5 "github.com/llgcode/draw2d" 6 7 "golang.org/x/image/math/fixed" 8) 9 10// DrawContour draws the given closed contour at the given sub-pixel offset. 11func DrawContour(path draw2d.PathBuilder, ps []truetype.Point, dx, dy float64) { 12 if len(ps) == 0 { 13 return 14 } 15 startX, startY := pointToF64Point(ps[0]) 16 path.MoveTo(startX+dx, startY+dy) 17 q0X, q0Y, on0 := startX, startY, true 18 for _, p := range ps[1:] { 19 qX, qY := pointToF64Point(p) 20 on := p.Flags&0x01 != 0 21 if on { 22 if on0 { 23 path.LineTo(qX+dx, qY+dy) 24 } else { 25 path.QuadCurveTo(q0X+dx, q0Y+dy, qX+dx, qY+dy) 26 } 27 } else { 28 if on0 { 29 // No-op. 30 } else { 31 midX := (q0X + qX) / 2 32 midY := (q0Y + qY) / 2 33 path.QuadCurveTo(q0X+dx, q0Y+dy, midX+dx, midY+dy) 34 } 35 } 36 q0X, q0Y, on0 = qX, qY, on 37 } 38 // Close the curve. 39 if on0 { 40 path.LineTo(startX+dx, startY+dy) 41 } else { 42 path.QuadCurveTo(q0X+dx, q0Y+dy, startX+dx, startY+dy) 43 } 44} 45 46func pointToF64Point(p truetype.Point) (x, y float64) { 47 return fUnitsToFloat64(p.X), -fUnitsToFloat64(p.Y) 48} 49 50func fUnitsToFloat64(x fixed.Int26_6) float64 { 51 scaled := x << 2 52 return float64(scaled/256) + float64(scaled%256)/256.0 53} 54 55// FontExtents contains font metric information. 56type FontExtents struct { 57 // Ascent is the distance that the text 58 // extends above the baseline. 59 Ascent float64 60 61 // Descent is the distance that the text 62 // extends below the baseline. The descent 63 // is given as a negative value. 64 Descent float64 65 66 // Height is the distance from the lowest 67 // descending point to the highest ascending 68 // point. 69 Height float64 70} 71 72// Extents returns the FontExtents for a font. 73// TODO needs to read this https://developer.apple.com/fonts/TrueType-Reference-Manual/RM02/Chap2.html#intro 74func Extents(font *truetype.Font, size float64) FontExtents { 75 bounds := font.Bounds(fixed.Int26_6(font.FUnitsPerEm())) 76 scale := size / float64(font.FUnitsPerEm()) 77 return FontExtents{ 78 Ascent: float64(bounds.Max.Y) * scale, 79 Descent: float64(bounds.Min.Y) * scale, 80 Height: float64(bounds.Max.Y-bounds.Min.Y) * scale, 81 } 82} 83