font/sfnt: implement rcurveline and rlinecurve.

Change-Id: I563f9e4a76a5c91d2ef2b6ffccc78550ab582d08
Reviewed-on: https://go-review.googlesource.com/38110
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/font/sfnt/postscript.go b/font/sfnt/postscript.go
index ca1b831..c92ea4a 100644
--- a/font/sfnt/postscript.go
+++ b/font/sfnt/postscript.go
@@ -564,8 +564,8 @@
 		21: {-1, "rmoveto", t2CRmoveto},
 		22: {-1, "hmoveto", t2CHmoveto},
 		23: {-1, "vstemhm", t2CStem},
-		24: {}, // rcurveline.
-		25: {}, // rlinecurve.
+		24: {-1, "rcurveline", t2CRcurveline},
+		25: {-1, "rlinecurve", t2CRlinecurve},
 		26: {-1, "vvcurveto", t2CVvcurveto},
 		27: {-1, "hhcurveto", t2CHhcurveto},
 		28: {}, // shortint.
@@ -736,10 +736,7 @@
 func t2CVlineto(p *psInterpreter) error { return t2CLineto(p, true) }
 
 func t2CLineto(p *psInterpreter, vertical bool) error {
-	if !p.type2Charstrings.seenWidth {
-		return errInvalidCFFTable
-	}
-	if p.stack.top < 1 {
+	if !p.type2Charstrings.seenWidth || p.stack.top < 1 {
 		return errInvalidCFFTable
 	}
 	for i := int32(0); i < p.stack.top; i, vertical = i+1, !vertical {
@@ -754,10 +751,7 @@
 }
 
 func t2CRlineto(p *psInterpreter) error {
-	if !p.type2Charstrings.seenWidth {
-		return errInvalidCFFTable
-	}
-	if p.stack.top < 2 || p.stack.top%2 != 0 {
+	if !p.type2Charstrings.seenWidth || p.stack.top < 2 || p.stack.top%2 != 0 {
 		return errInvalidCFFTable
 	}
 	for i := int32(0); i < p.stack.top; i += 2 {
@@ -770,6 +764,56 @@
 
 // As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
 //
+// rcurveline is:
+//	- {dxa dya dxb dyb dxc dyc}+ dxd dyd
+//
+// rlinecurve is:
+//	- {dxa dya}+ dxb dyb dxc dyc dxd dyd
+
+func t2CRcurveline(p *psInterpreter) error {
+	if !p.type2Charstrings.seenWidth || p.stack.top < 8 || p.stack.top%6 != 2 {
+		return errInvalidCFFTable
+	}
+	i := int32(0)
+	for iMax := p.stack.top - 2; i < iMax; i += 6 {
+		t2CAppendCubeto(p,
+			p.stack.a[i+0],
+			p.stack.a[i+1],
+			p.stack.a[i+2],
+			p.stack.a[i+3],
+			p.stack.a[i+4],
+			p.stack.a[i+5],
+		)
+	}
+	p.type2Charstrings.x += p.stack.a[i+0]
+	p.type2Charstrings.y += p.stack.a[i+1]
+	t2CAppendLineto(p)
+	return nil
+}
+
+func t2CRlinecurve(p *psInterpreter) error {
+	if !p.type2Charstrings.seenWidth || p.stack.top < 8 || p.stack.top%2 != 0 {
+		return errInvalidCFFTable
+	}
+	i := int32(0)
+	for iMax := p.stack.top - 6; i < iMax; i += 2 {
+		p.type2Charstrings.x += p.stack.a[i+0]
+		p.type2Charstrings.y += p.stack.a[i+1]
+		t2CAppendLineto(p)
+	}
+	t2CAppendCubeto(p,
+		p.stack.a[i+0],
+		p.stack.a[i+1],
+		p.stack.a[i+2],
+		p.stack.a[i+3],
+		p.stack.a[i+4],
+		p.stack.a[i+5],
+	)
+	return nil
+}
+
+// As per 5177.Type2.pdf section 4.1 "Path Construction Operators",
+//
 // hhcurveto is:
 //	- dy1 {dxa dxb dyb dxc}+
 //
diff --git a/font/sfnt/proprietary_test.go b/font/sfnt/proprietary_test.go
index b105ee5..2e127b6 100644
--- a/font/sfnt/proprietary_test.go
+++ b/font/sfnt/proprietary_test.go
@@ -380,6 +380,26 @@
 			// -90 38 83 -66 121 hhcurveto
 			cubeTo(329, -99, 412, -165, 533, -165),
 		},
+		'Λ': { // U+039B GREEK CAPITAL LETTER LAMDA
+			// 0 vmoveto
+			moveTo(0, 0),
+			// 85 hlineto
+			lineTo(85, 0),
+			// 105 355 23 77 16 63 24 77 rlinecurve
+			lineTo(190, 355),
+			cubeTo(213, 432, 229, 495, 253, 572),
+			// 4 hlineto
+			lineTo(257, 572),
+			// 25 -77 16 -63 23 -77 106 -355 rcurveline
+			cubeTo(282, 495, 298, 432, 321, 355),
+			lineTo(427, 0),
+			// 88 hlineto
+			lineTo(515, 0),
+			// -210 656 rlineto
+			lineTo(305, 656),
+			// -96 hlineto
+			lineTo(209, 656),
+		},
 	},
 
 	"microsoft/Arial.ttf": {