-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
1,206 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ old/* | |
*.json | ||
.vscode/* | ||
*/*/test/* | ||
*/test/* | ||
*/test/* | ||
test/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package gdf | ||
|
||
import ( | ||
"math" | ||
) | ||
|
||
func unitCircle(theta float64) (p Point) { | ||
p.Y, p.X = math.Sincos(theta) | ||
return p | ||
} | ||
|
||
func circleDxDy(theta float64) (dx, dy float64) { | ||
dx, dy = math.Sincos(theta) | ||
return -dx, dy | ||
} | ||
|
||
// Affine transformations of Points | ||
|
||
func (p *Point) scale(x, y float64) *Point { | ||
p.X *= x | ||
p.Y *= y | ||
return p | ||
} | ||
|
||
func (p *Point) translate(dx, dy float64) *Point { | ||
p.X += dx | ||
p.Y += dy | ||
return p | ||
} | ||
|
||
func (p *Point) rotate(theta float64) *Point { | ||
sin, cos := math.Sincos(theta) | ||
x, y := p.X, p.Y | ||
p.X = x*cos - y*sin | ||
p.Y = x*sin + y*cos | ||
return p | ||
} | ||
|
||
// Returns the distance between a unit circle segment end point and its Bézier control point for a given theta. | ||
func kappa(theta float64) float64 { return 4. / 3. * math.Tan(theta/4.) } | ||
|
||
// basic arc returns the arc from theta to theta+delta iff delta <= pi. | ||
func basicArc(theta, delta float64) (p1, q1, q2, p2 Point) { | ||
p1 = unitCircle(0) | ||
p2 = unitCircle(delta) | ||
|
||
k := kappa(delta) | ||
|
||
dx, dy := circleDxDy(0) | ||
q1.X = p1.X - dx*k | ||
q1.Y = p1.Y + dy*k | ||
|
||
dx, dy = circleDxDy(delta) | ||
q2.X = p2.X - dx*k | ||
q2.Y = p2.Y - dy*k | ||
|
||
p1.rotate(theta) | ||
q1.rotate(theta) | ||
q2.rotate(theta) | ||
p2.rotate(theta) | ||
return p1, q1, q2, p2 | ||
} | ||
|
||
// Arc draws an elliptic arc. If e is an ellipse defined by the parametric | ||
// function y(theta) = cy + ry*sin(theta) and x(theta) = cx + rx*cos(theta), | ||
// then the arc is the segment of the ellipse that begins at e(theta) and | ||
// ends at e(theta+delta). If delta is negative, the arc is drawn clockwise. | ||
func (c *ContentStream) Arc(cx, cy, rx, ry, theta, delta float64) { | ||
c.Arc2(cx, cy, rx, ry, theta, delta, 0, math.Pi/2.) | ||
} | ||
|
||
// Circle begins a new path and appends a circle of radius r with a center point of (cx, cy) to the path. | ||
// The new current point becomes (cx + r, cy). | ||
func (c *ContentStream) Circle(cx, cy, r float64) { | ||
c.Arc2(cx, cy, r, r, 0, 2*math.Pi, 0, math.Pi/4.) | ||
} | ||
|
||
// Ellipse begins a new path and appends an ellipse with a center point of (cx, cy), an x-radius of rx, and | ||
// a y-radius of ry to the path. | ||
func (c *ContentStream) Ellipse(cx, cy, rx, ry float64) { | ||
c.Arc2(cx, cy, rx, ry, 0, 2*math.Pi, 0, math.Pi/4.) | ||
} | ||
|
||
// Arc2 draws an elliptic arc. It is similar to Arc, but includes additional parameters. phi indicates | ||
// an angle relative to the x-axis that the arc is rotated about its center point. step is the maximum | ||
// size in radians of each segment of the arc. This value must be greater than 0 and less than or equal | ||
// to pi. Lower values increase the accuracy of the arc, but can cause significant performance degradations. | ||
// In practice, values of pi/2 and pi/4 are reasonable upper- and lower-bounds. The Arc method uses | ||
// pi/2 by default. Note: the step argument has no effect on arcs with deltas that have an absolute value | ||
// less than the value of step. | ||
func (c *ContentStream) Arc2(cx, cy, rx, ry, theta, delta, phi, step float64) { | ||
var tau = min(math.Abs(step), math.Pi) | ||
if tau <= 0 { | ||
tau = math.Pi / 8. | ||
} | ||
var p1, q1, q2, p2 Point | ||
if delta > 0 { | ||
for beta := 0.0; beta < delta; beta += tau { | ||
p1, q1, q2, p2 = basicArc(theta, min(tau, delta-beta)) | ||
p1.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
q1.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
q2.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
p2.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
if beta == 0 { | ||
c.MoveTo(p1.X, p1.Y) | ||
} | ||
c.CubicBezier1(q1.X, q1.Y, q2.X, q2.Y, p2.X, p2.Y) | ||
theta += tau | ||
} | ||
|
||
} else if delta < 0 { | ||
for beta := 0.0; beta > delta; beta -= tau { | ||
p1, q1, q2, p2 := basicArc(theta, max(-tau, delta-beta)) | ||
p1.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
q1.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
q2.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
p2.scale(rx, ry).rotate(phi).translate(cx, cy) | ||
if beta == 0 { | ||
c.MoveTo(p1.X, p1.Y) | ||
} | ||
c.CubicBezier1(q1.X, q1.Y, q2.X, q2.Y, p2.X, p2.Y) | ||
theta -= tau | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,108 @@ | ||
package gdf | ||
|
||
// graphics state ops (Table 56) | ||
const ( | ||
// graphics state ops (Table 56 | ||
op_q = "q\n" | ||
op_Q = "Q\n" | ||
op_cm = "cm\n" | ||
op_w = "w\n" | ||
op_J = "J\n" | ||
op_j = "j\n" | ||
op_M = "M\n" | ||
op_d = "d\n" | ||
op_ri = "ri\n" | ||
op_i = "i\n" | ||
op_gs = "gs\n" | ||
op_q = "q\n" // push graphics state | ||
op_Q = "Q\n" // pop graphics state | ||
op_cm = "cm\n" // concat matrix | ||
op_w = "w\n" // line width | ||
op_J = "J\n" // line cap | ||
op_j = "j\n" // line join | ||
op_M = "M\n" // miter limit | ||
op_d = "d\n" // dash pattern | ||
op_ri = "ri\n" // rendering intent | ||
op_i = "i\n" // flatness | ||
op_gs = "gs\n" // extended graphics state | ||
) | ||
|
||
// path construction ops (Table 58 | ||
op_m = "m\n" | ||
op_l = "l\n" | ||
op_c = "c\n" | ||
op_v = "v\n" | ||
op_y = "y\n" | ||
op_h = "h\n" | ||
op_re = "re\n" | ||
// path construction ops (Table 58) | ||
const ( | ||
op_m = "m\n" // begin subpath | ||
op_l = "l\n" // append line | ||
op_c = "c\n" // append cubic Bézier curve 1 | ||
op_v = "v\n" // append cubic Bézier curve 2 | ||
op_y = "y\n" // append cubic Bézier curve 3 | ||
op_h = "h\n" // close subpath | ||
op_re = "re\n" // append rectangle | ||
) | ||
|
||
// path painting ops (Table 59 | ||
op_S = "S\n" | ||
op_s = "s\n" | ||
op_f = "f\n" | ||
op_f_X = "f*\n" | ||
op_B = "B\n" | ||
op_B_X = "B*\n" | ||
op_b = "b\n" | ||
op_b_X = "b*\n" | ||
op_n = "n\n" | ||
// path painting ops (Table 59) | ||
const ( | ||
op_S = "S\n" // stroke path | ||
op_s = "s\n" // close and stroke path | ||
op_f = "f\n" // fill path non-zero winding | ||
op_f_X = "f*\n" // fill path even-odd | ||
op_B = "B\n" // fill path non-zero winding and then stroke path | ||
op_B_X = "B*\n" // fill path even-odd and then stroke path | ||
op_b = "b\n" // close path, fill path non-zero winding, and then stroke path | ||
op_b_X = "b*\n" // close path, fill path even-odd, and then stroke path | ||
op_n = "n\n" // end path without filling or stroking | ||
) | ||
|
||
// clipping path ops (Table 60 | ||
op_W = "W\n" | ||
op_W_X = "W*\n" | ||
// clipping path ops (Table 60) | ||
const ( | ||
op_W = "W\n" // intersect the clipping path with the current path using the non-zero winding rule | ||
op_W_X = "W*\n" // intersect the clipping path with the current path using the even-odd rule | ||
) | ||
|
||
// color ops (Table 73; upper | ||
op_CS = "CS\n" | ||
op_cs = "cs\n" | ||
op_SC = "SC\n" | ||
op_SCN = "SCN\n" | ||
op_sc = "sc\n" | ||
op_scn = "scn\n" | ||
op_G = "G\n" | ||
op_g = "g\n" | ||
op_RG = "RG\n" | ||
op_rg = "rg\n" | ||
op_K = "K\n" | ||
op_k = "k\n" | ||
// color ops (Table 73) | ||
const ( | ||
op_CS = "CS\n" // stroking color space | ||
op_cs = "cs\n" // nonstroking color space | ||
op_SC = "SC\n" // stroking color | ||
op_SCN = "SCN\n" // stroking color with support for additional color spaces | ||
op_sc = "sc\n" // nonstroking color | ||
op_scn = "scn\n" // nonstroking color with support for additional color spaces | ||
op_G = "G\n" // set stroking color to a DeviceGray color | ||
op_g = "g\n" // set nonstroking color to a DeviceGray color | ||
op_RG = "RG\n" // set stroking color to a DeviceRGB color | ||
op_rg = "rg\n" // set nonstroking color to a DeviceRGB color | ||
op_K = "K\n" // set stroking color to a DeviceCMYK color | ||
op_k = "k\n" // set nonstroking color to a DeviceCMYK color | ||
) | ||
|
||
// XObject op (Table 86 | ||
op_Do = "Do\n" | ||
// XObject op (Table 86) | ||
const ( | ||
op_Do = "Do\n" // print XObject | ||
) | ||
|
||
// text state ops (Table 103 | ||
op_Tc = "Tc\n" | ||
op_Tw = "Tw\n" | ||
op_Tz = "Tz\n" | ||
op_TL = "TL\n" | ||
op_Tf = "Tf\n" | ||
op_Tr = "Tr\n" | ||
op_Ts = "Ts\n" | ||
// text state ops (Table 103) | ||
const ( | ||
op_Tc = "Tc\n" // character spacing | ||
op_Tw = "Tw\n" // word spacing | ||
op_Tz = "Tz\n" // horizontal scaling | ||
op_TL = "TL\n" // text leading | ||
op_Tf = "Tf\n" // font size | ||
op_Tr = "Tr\n" // text rendering mode | ||
op_Ts = "Ts\n" // text rise | ||
) | ||
|
||
// text object ops (Table 105 | ||
op_BT = "BT\n" | ||
op_ET = "ET\n" | ||
// text object ops (Table 105) | ||
const ( | ||
op_BT = "BT\n" // begin text object | ||
op_ET = "ET\n" // end text object | ||
) | ||
|
||
// text positioning ops (Table 106 | ||
op_Td = "Td\n" | ||
op_TD = "TD\n" | ||
op_Tm = "Tm\n" | ||
op_T_X = "T*\n" | ||
// text positioning ops (Table 106) | ||
const ( | ||
op_Td = "Td\n" // new line with offset | ||
op_TD = "TD\n" // new line with offset and set leading | ||
op_Tm = "Tm\n" // text matrix | ||
op_T_X = "T*\n" // new line and set leading | ||
) | ||
|
||
// text showing ops (Table 107 | ||
op_Tj = "Tj\n" | ||
op_APOSTROPHE = "'\n" | ||
op_QUOTE = "\"\n" | ||
op_TJ = "TJ\n" | ||
// text showing ops (Table 107) | ||
const ( | ||
op_Tj = "Tj\n" // show text | ||
op_APOSTROPHE = "'\n" // move to new line and show text | ||
op_QUOTE = "\"\n" // move to new line and show text with character and word spacing | ||
op_TJ = "TJ\n" // show text arrays with glyph positioning | ||
) | ||
|
||
// marked content operators (Table 352 | ||
op_MP = "MP\n" | ||
op_DP = "DP\n" | ||
op_BMC = "BMC\n" | ||
op_EMC = "EMC\n" | ||
// marked content operators (Table 352) | ||
const ( | ||
op_MP = "MP\n" // tag marked-content point | ||
op_DP = "DP\n" // tag marked-content point with properties list | ||
op_BMC = "BMC\n" // begin marked-content sequence | ||
op_EMC = "EMC\n" // end marked-content sequence | ||
) |
Oops, something went wrong.