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": {