font: add a []byte flavor of string methods.

Change-Id: I2506067ba6ac12c275b65c3a52cb38579d4b9dca
Reviewed-on: https://go-review.googlesource.com/23464
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/font/font.go b/font/font.go
index a089e77..a0a66d2 100644
--- a/font/font.go
+++ b/font/font.go
@@ -13,6 +13,7 @@
 	"image"
 	"image/draw"
 	"io"
+	"unicode/utf8"
 
 	"golang.org/x/image/math/fixed"
 )
@@ -87,9 +88,6 @@
 	Descent fixed.Int26_6
 }
 
-// TODO: Drawer.Layout or Drawer.Measure methods to measure text without
-// drawing?
-
 // Drawer draws text on a destination image.
 //
 // A Drawer is not safe for concurrent use by multiple goroutines, since its
@@ -115,19 +113,25 @@
 // TODO: should DrawString return the last rune drawn, so the next DrawString
 // call can kern beforehand? Or should that be the responsibility of the caller
 // if they really want to do that, since they have to explicitly shift d.Dot
-// anyway?
+// anyway? What if ligatures span more than two runes? What if grapheme
+// clusters span multiple runes?
 //
-// In general, we'd have a DrawBytes([]byte) and DrawRuneReader(io.RuneReader)
-// and the last case can't assume that you can rewind the stream.
+// TODO: do we assume that the input is in any particular Unicode Normalization
+// Form?
+//
+// TODO: have DrawRunes(s []rune)? DrawRuneReader(io.RuneReader)?? If we take
+// io.RuneReader, we can't assume that we can rewind the stream.
 //
 // TODO: how does this work with line breaking: drawing text up until a
 // vertical line? Should DrawString return the number of runes drawn?
 
-// DrawString draws s at the dot and advances the dot's location.
-func (d *Drawer) DrawString(s string) {
-	var prevC rune
-	for i, c := range s {
-		if i != 0 {
+// DrawBytes draws s at the dot and advances the dot's location.
+func (d *Drawer) DrawBytes(s []byte) {
+	prevC := rune(-1)
+	for len(s) > 0 {
+		c, size := utf8.DecodeRune(s)
+		s = s[size:]
+		if prevC >= 0 {
 			d.Dot.X += d.Face.Kern(prevC, c)
 		}
 		dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
@@ -143,16 +147,63 @@
 	}
 }
 
+// DrawString draws s at the dot and advances the dot's location.
+func (d *Drawer) DrawString(s string) {
+	prevC := rune(-1)
+	for _, c := range s {
+		if prevC >= 0 {
+			d.Dot.X += d.Face.Kern(prevC, c)
+		}
+		dr, mask, maskp, advance, ok := d.Face.Glyph(d.Dot, c)
+		if !ok {
+			// TODO: is falling back on the U+FFFD glyph the responsibility of
+			// the Drawer or the Face?
+			// TODO: set prevC = '\ufffd'?
+			continue
+		}
+		draw.DrawMask(d.Dst, dr, d.Src, image.Point{}, mask, maskp, draw.Over)
+		d.Dot.X += advance
+		prevC = c
+	}
+}
+
+// MeasureBytes returns how far dot would advance by drawing s.
+func (d *Drawer) MeasureBytes(s []byte) (advance fixed.Int26_6) {
+	return MeasureBytes(d.Face, s)
+}
+
 // MeasureString returns how far dot would advance by drawing s.
 func (d *Drawer) MeasureString(s string) (advance fixed.Int26_6) {
 	return MeasureString(d.Face, s)
 }
 
+// MeasureBytes returns how far dot would advance by drawing s with f.
+func MeasureBytes(f Face, s []byte) (advance fixed.Int26_6) {
+	prevC := rune(-1)
+	for len(s) > 0 {
+		c, size := utf8.DecodeRune(s)
+		s = s[size:]
+		if prevC >= 0 {
+			advance += f.Kern(prevC, c)
+		}
+		a, ok := f.GlyphAdvance(c)
+		if !ok {
+			// TODO: is falling back on the U+FFFD glyph the responsibility of
+			// the Drawer or the Face?
+			// TODO: set prevC = '\ufffd'?
+			continue
+		}
+		advance += a
+		prevC = c
+	}
+	return advance
+}
+
 // MeasureString returns how far dot would advance by drawing s with f.
 func MeasureString(f Face, s string) (advance fixed.Int26_6) {
-	var prevC rune
-	for i, c := range s {
-		if i != 0 {
+	prevC := rune(-1)
+	for _, c := range s {
+		if prevC >= 0 {
 			advance += f.Kern(prevC, c)
 		}
 		a, ok := f.GlyphAdvance(c)