func (cdc *Codec) MarshalBinaryLengthPrefixedWriter(w io.Writer, o interface{}) (n int64, err error) {
	var bz, _n = []byte(nil), int(0)
	bz, err = cdc.MarshalBinaryLengthPrefixed(o)
	if err != nil {
		return 0, err
	}
	_n, err = w.Write(bz) // TODO: handle overflow in 32-bit systems.
	n = int64(_n)
	return
}

// MarshalBinaryLengthPrefixedWriter writes the bytes as would be returned from
// MarshalBinaryLengthPrefixed to the writer w.

MarshalBinaryLengthPrefixedWriter writes the bytes as would be returned from MarshalBinaryLengthPrefixed to the writer w .


func (cdc *Codec) MarshalBinaryBare(o interface{}) ([]byte, error) {

	// Dereference value if pointer.
	var rv, _, isNilPtr = derefPointers(reflect.ValueOf(o))
	if isNilPtr {
		// NOTE: You can still do so by calling
		// `.MarshalBinaryLengthPrefixed(struct{ *SomeType })` or so on.
		panic("MarshalBinaryBare cannot marshal a nil pointer directly. Try wrapping in a struct?")
	}

	// Encode Amino:binary bytes.
	var bz []byte
	buf := new(bytes.Buffer)
	rt := rv.Type()
	info, err := cdc.getTypeInfo_wlock(rt)
	if err != nil {
		return nil, err
	}
	err = cdc.encodeReflectBinary(buf, info, rv, FieldOptions{BinFieldNum: 1}, true)
	if err != nil {
		return nil, err
	}
	bz = buf.Bytes()

	// If registered concrete, prepend prefix bytes.
	if info.Registered {
		pb := info.Prefix.Bytes()
		bz = append(pb, bz...)
	}

	return bz, nil
}

// MarshalBinaryBare encodes the object o according to the Amino spec.
// MarshalBinaryBare doesn't prefix the byte-length of the encoding,
// so the caller must handle framing.

MarshalBinaryBare encodes the object o according to the Amino spec . MarshalBinaryBare doesn t prefix the byte - length of the encoding so the caller must handle framing .


func (cdc *Codec) UnmarshalBinaryLengthPrefixed(bz []byte, ptr interface{}) error {
	if len(bz) == 0 {
		return errors.New("UnmarshalBinaryLengthPrefixed cannot decode empty bytes")
	}

	// Read byte-length prefix.
	u64, n := binary.Uvarint(bz)
	if n < 0 {
		return fmt.Errorf("Error reading msg byte-length prefix: got code %v", n)
	}
	if u64 > uint64(len(bz)-n) {
		return fmt.Errorf("Not enough bytes to read in UnmarshalBinaryLengthPrefixed, want %v more bytes but only have %v",
			u64, len(bz)-n)
	} else if u64 < uint64(len(bz)-n) {
		return fmt.Errorf("Bytes left over in UnmarshalBinaryLengthPrefixed, should read %v more bytes but have %v",
			u64, len(bz)-n)
	}
	bz = bz[n:]

	// Decode.
	return cdc.UnmarshalBinaryBare(bz, ptr)
}

func
(
cdc
*
Codec
)
UnmarshalBinaryLengthPrefixed
(
bz
[
]
byte
,
ptr
interface
{
}
)
error
{
if
len
(
bz
)
==
0
{
return
errors
.
New
(
"
"
)
}
// Read byte-length prefix.
u64
,
n
:=
binary
.
Uvarint
(
bz
)
if
n
<
0
{
return
fmt
.
Errorf
(
"
"
,
n
)
}
if
u64
>
uint64
(
len
(
bz
)
n
)
{
return
fmt
.
Errorf
(
"
"
,
u64
,
len
(
bz
)
n
)
}
else
if
u64
<
uint64
(
len
(
bz
)
n
)
{
return
fmt
.
Errorf
(
"
"
,
u64
,
len
(
bz
)
n
)
}
bz
=
bz
[
n
:
]
// Decode.
return
cdc
.
UnmarshalBinaryBare
(
bz
,
ptr
)
}

// Like UnmarshalBinaryBare, but will first decode the byte-length prefix.
// UnmarshalBinaryLengthPrefixed will panic if ptr is a nil-pointer.
// Returns an error if not all of bz is consumed.

Like UnmarshalBinaryBare but will first decode the byte - length prefix . UnmarshalBinaryLengthPrefixed will panic if ptr is a nil - pointer . Returns an error if not all of bz is consumed .


func (cdc *Codec) UnmarshalBinaryBare(bz []byte, ptr interface{}) error {

	rv := reflect.ValueOf(ptr)
	if rv.Kind() != reflect.Ptr {
		panic("Unmarshal expects a pointer")
	}
	rv = rv.Elem()
	rt := rv.Type()
	info, err := cdc.getTypeInfo_wlock(rt)
	if err != nil {
		return err
	}
	// If registered concrete, consume and verify prefix bytes.
	if info.Registered {
		pb := info.Prefix.Bytes()
		if len(bz) < 4 {
			return fmt.Errorf("UnmarshalBinaryBare expected to read prefix bytes %X (since it is registered concrete) but got %X", pb, bz)
		} else if !bytes.Equal(bz[:4], pb) {
			return fmt.Errorf("UnmarshalBinaryBare expected to read prefix bytes %X (since it is registered concrete) but got %X...", pb, bz[:4])
		}
		bz = bz[4:]
	}
	// Decode contents into rv.
	n, err := cdc.decodeReflectBinary(bz, info, rv, FieldOptions{BinFieldNum: 1}, true)
	if err != nil {
		return fmt.Errorf("unmarshal to %v failed after %d bytes (%v): %X", info.Type, n, err, bz)
	}
	if n != len(bz) {
		return fmt.Errorf("unmarshal to %v didn't read all bytes. Expected to read %v, only read %v: %X", info.Type, len(bz), n, bz)
	}
	return nil
}

// UnmarshalBinaryBare will panic if ptr is a nil-pointer.

UnmarshalBinaryBare will panic if ptr is a nil - pointer .


func (cdc *Codec) MustMarshalJSON(o interface{}) []byte {
	bz, err := cdc.MarshalJSON(o)
	if err != nil {
		panic(err)
	}
	return bz
}

func ( cdc * Codec ) MustMarshalJSON ( o interface { } ) [ ] byte { bz , err := cdc . MarshalJSON ( o ) if err != nil { panic ( err ) } return bz }

// MustMarshalJSON panics if an error occurs. Besides tha behaves exactly like MarshalJSON.

MustMarshalJSON panics if an error occurs . Besides tha behaves exactly like MarshalJSON .


func (cdc *Codec) MustUnmarshalJSON(bz []byte, ptr interface{}) {
	if err := cdc.UnmarshalJSON(bz, ptr); err != nil {
		panic(err)
	}
}

func ( cdc * Codec ) MustUnmarshalJSON ( bz [ ] byte , ptr interface { } ) { if err := cdc . UnmarshalJSON ( bz , ptr ) ; err != nil { panic ( err ) } }

// MustUnmarshalJSON panics if an error occurs. Besides tha behaves exactly like UnmarshalJSON.

MustUnmarshalJSON panics if an error occurs . Besides tha behaves exactly like UnmarshalJSON .


func (cdc *Codec) MarshalJSONIndent(o interface{}, prefix, indent string) ([]byte, error) {
	bz, err := cdc.MarshalJSON(o)
	if err != nil {
		return nil, err
	}
	var out bytes.Buffer
	err = json.Indent(&out, bz, prefix, indent)
	if err != nil {
		return nil, err
	}
	return out.Bytes(), nil
}

func ( cdc * Codec ) MarshalJSONIndent ( o interface { } , prefix , indent string ) ( [ ] byte , error ) { bz , err := cdc . MarshalJSON ( o ) if err != nil { return nil , err } var out bytes . Buffer err = json . Indent ( & out , bz , prefix , indent ) if err != nil { return nil , err } return out . Bytes ( ) , nil }

// MarshalJSONIndent calls json.Indent on the output of cdc.MarshalJSON
// using the given prefix and indent string.

MarshalJSONIndent calls json . Indent on the output of cdc . MarshalJSON using the given prefix and indent string .


func newDataReader(r io.Reader) *internalDataReader {
	buffered := bufio.NewReader(r)

	reader := internalDataReader{
		wrapped:r,
		buffered:buffered,
	}

	return &reader
}

func newDataReader ( r io . Reader ) * internalDataReader { buffered := bufio . NewReader ( r ) reader := internalDataReader { wrapped : r , buffered : buffered , } return & reader }

// newDataReader creates a new DataReader reading from 'r'.

newDataReader creates a new DataReader reading from r .


func (r *internalDataReader) Read(data []byte) (n int, err error) {

	const IAC = 255

	const SB = 250
	const SE = 240

	const WILL = 251
	const WONT = 252
	const DO   = 253
	const DONT = 254

	p := data

	for len(p) > 0 {
		var b byte

		b, err = r.buffered.ReadByte()
		if nil != err {
			return n, err
		}

		if IAC == b {
			var peeked []byte

			peeked, err = r.buffered.Peek(1)
			if nil != err {
				return n, err
			}

			switch peeked[0] {
			case WILL, WONT, DO, DONT:
				_, err = r.buffered.Discard(2)
				if nil != err {
					return n, err
				}
			case IAC:
				p[0] = IAC
				n++
				p = p[1:]

				_, err = r.buffered.Discard(1)
				if nil != err {
					return n, err
				}
			case SB:
				for {
					var b2 byte
					b2, err = r.buffered.ReadByte()
					if nil != err {
						return n, err
					}

					if IAC == b2 {
						peeked, err = r.buffered.Peek(1)
						if nil != err {
							return n, err
						}

						if IAC == peeked[0] {
							_, err = r.buffered.Discard(1)
							if nil != err {
								return n, err
							}
						}

						if SE == peeked[0] {
							_, err = r.buffered.Discard(1)
							if nil != err {
								return n, err
							}
							break
						}
					}
				}
			case SE:
				_, err = r.buffered.Discard(1)
				if nil != err {
					return n, err
				}
			default:
				// If we get in here, this is not following the TELNET protocol.
//@TODO: Make a better error.
				err = errCorrupted
				return n, err
			}
		} else {

			p[0] = b
			n++
			p = p[1:]
		}
	}

	return n, nil
}

// Read reads the TELNET escaped data from the  wrapped io.Reader, and "un-escapes" it into 'data'.

Read reads the TELNET escaped data from the wrapped io . Reader and un - escapes it into data .


func (server *Server) ListenAndServeTLS(certFile string, keyFile string) error {

	addr := server.Addr
	if "" == addr {
		addr = ":telnets"
	}

	listener, err := net.Listen("tcp", addr)
	if nil != err {
		return err
	}

	// Apparently have to make a copy of the TLS config this way, rather than by
	// simple assignment, to prevent some unexported fields from being copied over.
	//
	// It would be nice if tls.Config had a method that would do this "safely".
	// (I.e., what happens if in the future more exported fields are added to
	// tls.Config?)
	var tlsConfig *tls.Config = nil
	if nil == server.TLSConfig {
		tlsConfig = &tls.Config{}
	} else {
		tlsConfig = &tls.Config{
			Rand:                     server.TLSConfig.Rand,
			Time:                     server.TLSConfig.Time,
			Certificates:             server.TLSConfig.Certificates,
			NameToCertificate:        server.TLSConfig.NameToCertificate,
			GetCertificate:           server.TLSConfig.GetCertificate,
			RootCAs:                  server.TLSConfig.RootCAs,
			NextProtos:               server.TLSConfig.NextProtos,
			ServerName:               server.TLSConfig.ServerName,
			ClientAuth:               server.TLSConfig.ClientAuth,
			ClientCAs:                server.TLSConfig.ClientCAs,
			InsecureSkipVerify:       server.TLSConfig.InsecureSkipVerify,
			CipherSuites:             server.TLSConfig.CipherSuites,
			PreferServerCipherSuites: server.TLSConfig.PreferServerCipherSuites,
			SessionTicketsDisabled:   server.TLSConfig.SessionTicketsDisabled,
			SessionTicketKey:         server.TLSConfig.SessionTicketKey,
			ClientSessionCache:       server.TLSConfig.ClientSessionCache,
			MinVersion:               server.TLSConfig.MinVersion,
			MaxVersion:               server.TLSConfig.MaxVersion,
			CurvePreferences:         server.TLSConfig.CurvePreferences,
		}
	}

	tlsConfigHasCertificate := len(tlsConfig.Certificates) > 0 || nil != tlsConfig.GetCertificate
	if "" == certFile || "" == keyFile || !tlsConfigHasCertificate {
		tlsConfig.Certificates = make([]tls.Certificate, 1)

		var err error
		tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
		if nil != err {
			return err
		}
	}

	tlsListener := tls.NewListener(listener, tlsConfig)

	return server.Serve(tlsListener)
}

// ListenAndServeTLS acts identically to ListenAndServe, except that it
// uses the TELNET protocol over TLS.
//
// From a TELNET protocol point-of-view, it allows for 'secured telnet', also known as TELNETS,
// which by default listens to port 992.

ListenAndServeTLS acts identically to ListenAndServe except that it uses the TELNET protocol over TLS . From a TELNET protocol point - of - view it allows for secured telnet also known as TELNETS which by default listens to port 992 .


func (fn ProducerFunc) Produce(ctx telnet.Context, name string, args ...string) Handler {
	return fn(ctx, name, args...)
}

func ( fn ProducerFunc ) Produce ( ctx telnet . Context , name string , args ... string ) Handler { return fn ( ctx , name , args ... ) }

// Produce makes ProducerFunc fit the Producer interface.

Produce makes ProducerFunc fit the Producer interface .


func PromoteHandlerFunc(fn HandlerFunc, args ...string) Handler {
	stdin,      stdinPipe := io.Pipe()
	stdoutPipe, stdout    := io.Pipe()
	stderrPipe, stderr    := io.Pipe()

	argsCopy := make([]string, len(args))
	for i, datum := range args {
		argsCopy[i] = datum
	}

	handler := internalPromotedHandlerFunc{
		err:nil,

		fn:fn,

		stdin:stdin,
		stdout:stdout,
		stderr:stderr,

		stdinPipe:stdinPipe,
		stdoutPipe:stdoutPipe,
		stderrPipe:stderrPipe,

		args:argsCopy,
	}

	return &handler
}

func PromoteHandlerFunc ( fn HandlerFunc , args ... string ) Handler { stdin , stdinPipe := io . Pipe ( ) stdoutPipe , stdout := io . Pipe ( ) stderrPipe , stderr := io . Pipe ( ) argsCopy := make ( [ ] string , len ( args ) ) for i , datum := range args { argsCopy [ i ] = datum } handler := internalPromotedHandlerFunc { err : nil , fn : fn , stdin : stdin , stdout : stdout , stderr : stderr , stdinPipe : stdinPipe , stdoutPipe : stdoutPipe , stderrPipe : stderrPipe , args : argsCopy , } return & handler }

// PromoteHandlerFunc turns a HandlerFunc into a Handler.

PromoteHandlerFunc turns a HandlerFunc into a Handler .


func Serve(listener net.Listener, handler Handler) error {

	server := &Server{Handler: handler}
	return server.Serve(listener)
}

func Serve ( listener net . Listener , handler Handler ) error { server := & Server { Handler : handler } return server . Serve ( listener ) }

// Serve accepts an incoming TELNET or TELNETS client connection on the net.Listener `listener`.

Serve accepts an incoming TELNET or TELNETS client connection on the net . Listener listener .


func (server *Server) Serve(listener net.Listener) error {

	defer listener.Close()

	logger := server.logger()

	handler := server.Handler
	if nil == handler {
//@TODO: Should this be a "ShellHandler" instead, that gives a shell-like experience by default
//       If this is changd, then need to change the comment in the "type Server struct" definition.
		logger.Debug("Defaulted handler to EchoHandler.")
		handler = EchoHandler
	}

	for {
		// Wait for a new TELNET client connection.
		logger.Debugf("Listening at %q.", listener.Addr())
		conn, err := listener.Accept()
		if err != nil {
//@TODO: Could try to recover from certain kinds of errors. Maybe waiting a while before trying again.
			return err
		}
		logger.Debugf("Received new connection from %q.", conn.RemoteAddr())

		// Handle the new TELNET client connection by spawning
		// a new goroutine.
		go server.handle(conn, handler)
		logger.Debugf("Spawned handler to handle connection from %q.", conn.RemoteAddr())
	}
}

// Serve accepts an incoming TELNET client connection on the net.Listener `listener`.

Serve accepts an incoming TELNET client connection on the net . Listener listener .


func (p *Parser) Fail(msg string) {
	p.WriteUsage(os.Stderr)
	fmt.Fprintln(os.Stderr, "error:", msg)
	os.Exit(-1)
}

func ( p * Parser ) Fail ( msg string ) { p . WriteUsage ( os . Stderr ) fmt . Fprintln ( os . Stderr , " " , msg ) os . Exit ( - 1 ) }

// Fail prints usage information to stderr and exits with non-zero status

Fail prints usage information to stderr and exits with non - zero status


func (p *Parser) WriteUsage(w io.Writer) {
	var positionals, options []*spec
	for _, spec := range p.specs {
		if spec.positional {
			positionals = append(positionals, spec)
		} else {
			options = append(options, spec)
		}
	}

	if p.version != "" {
		fmt.Fprintln(w, p.version)
	}

	fmt.Fprintf(w, "Usage: %s", p.config.Program)

	// write the option component of the usage message
	for _, spec := range options {
		// prefix with a space
		fmt.Fprint(w, " ")
		if !spec.required {
			fmt.Fprint(w, "[")
		}
		fmt.Fprint(w, synopsis(spec, "--"+spec.long))
		if !spec.required {
			fmt.Fprint(w, "]")
		}
	}

	// write the positional component of the usage message
	for _, spec := range positionals {
		// prefix with a space
		fmt.Fprint(w, " ")
		up := strings.ToUpper(spec.long)
		if spec.multiple {
			if !spec.required {
				fmt.Fprint(w, "[")
			}
			fmt.Fprintf(w, "%s [%s ...]", up, up)
			if !spec.required {
				fmt.Fprint(w, "]")
			}
		} else {
			fmt.Fprint(w, up)
		}
	}
	fmt.Fprint(w, "\n")
}

// WriteUsage writes usage information to the given writer


func (p *Parser) WriteHelp(w io.Writer) {
	var positionals, options []*spec
	for _, spec := range p.specs {
		if spec.positional {
			positionals = append(positionals, spec)
		} else {
			options = append(options, spec)
		}
	}

	if p.description != "" {
		fmt.Fprintln(w, p.description)
	}
	p.WriteUsage(w)

	// write the list of positionals
	if len(positionals) > 0 {
		fmt.Fprint(w, "\nPositional arguments:\n")
		for _, spec := range positionals {
			left := "  " + strings.ToUpper(spec.long)
			fmt.Fprint(w, left)
			if spec.help != "" {
				if len(left)+2 < colWidth {
					fmt.Fprint(w, strings.Repeat(" ", colWidth-len(left)))
				} else {
					fmt.Fprint(w, "\n"+strings.Repeat(" ", colWidth))
				}
				fmt.Fprint(w, spec.help)
			}
			fmt.Fprint(w, "\n")
		}
	}

	// write the list of options
	fmt.Fprint(w, "\nOptions:\n")
	for _, spec := range options {
		printOption(w, spec)
	}

	// write the list of built in options
	printOption(w, &spec{boolean: true, long: "help", short: "h", help: "display this help and exit"})
	if p.version != "" {
		printOption(w, &spec{boolean: true, long: "version", help: "display version and exit"})
	}
}

func
(
p
*
Parser
)
WriteHelp
(
w
io
.
Writer
)
{
var
positionals
,
options
[
]
*
spec
for
_
,
spec
:=
range
p
.
specs
{
if
spec
.
positional
{
positionals
=
append
(
positionals
,
spec
)
}
else
{
options
=
append
(
options
,
spec
)
}
}
if
p
.
description
!=
"
"
{
fmt
.
Fprintln
(
w
,
p
.
description
)
}
p
.
WriteUsage
(
w
)
// write the list of positionals
if
len
(
positionals
)
>
0
{
fmt
.
Fprint
(
w
,
"
\n
\n
"
)
for
_
,
spec
:=
range
positionals
{
left
:=
"
"
+
strings
.
ToUpper
(
spec
.
long
)
fmt
.
Fprint
(
w
,
left
)
if
spec
.
help
!=
"
"
{
if
len
(
left
)
+
2
<
colWidth
{
fmt
.
Fprint
(
w
,
strings
.
Repeat
(
"
"
,
colWidth
len
(
left
)
)
)
}
else
{
fmt
.
Fprint
(
w
,
"
\n
"
+
strings
.
Repeat
(
"
"
,
colWidth
)
)
}
fmt
.
Fprint
(
w
,
spec
.
help
)
}
fmt
.
Fprint
(
w
,
"
\n
"
)
}
}
// write the list of options
fmt
.
Fprint
(
w
,
"
\n
\n
"
)
for
_
,
spec
:=
range
options
{
printOption
(
w
,
spec
)
}
// write the list of built in options
printOption
(
w
,
&
spec
{
boolean
:
true
,
long
:
"
"
,
short
:
"
"
,
help
:
"
"
}
)
if
p
.
version
!=
"
"
{
printOption
(
w
,
&
spec
{
boolean
:
true
,
long
:
"
"
,
help
:
"
"
}
)
}
}

// WriteHelp writes the usage string followed by the full help string for each option


func MustParse(dest ...interface{}) *Parser {
	p, err := NewParser(Config{}, dest...)
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	err = p.Parse(flags())
	if err == ErrHelp {
		p.WriteHelp(os.Stdout)
		os.Exit(0)
	}
	if err == ErrVersion {
		fmt.Println(p.version)
		os.Exit(0)
	}
	if err != nil {
		p.Fail(err.Error())
	}
	return p
}

func MustParse ( dest ... interface { } ) * Parser { p , err := NewParser ( Config { } , dest ... ) if err != nil { fmt . Println ( err ) os . Exit ( - 1 ) } err = p . Parse ( flags ( ) ) if err == ErrHelp { p . WriteHelp ( os . Stdout ) os . Exit ( 0 ) } if err == ErrVersion { fmt . Println ( p . version ) os . Exit ( 0 ) } if err != nil { p . Fail ( err . Error ( ) ) } return p }

// MustParse processes command line arguments and exits upon failure


func Parse(dest ...interface{}) error {
	p, err := NewParser(Config{}, dest...)
	if err != nil {
		return err
	}
	return p.Parse(flags())
}

func Parse ( dest ... interface { } ) error { p , err := NewParser ( Config { } , dest ... ) if err != nil { return err } return p . Parse ( flags ( ) ) }

// Parse processes command line arguments and stores them in dest


func walkFields(v reflect.Value, visit func(field reflect.StructField, val reflect.Value, owner reflect.Type) bool) {
	t := v.Type()
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		val := v.Field(i)
		expand := visit(field, val, t)
		if expand && field.Type.Kind() == reflect.Struct {
			walkFields(val, visit)
		}
	}
}

func walkFields ( v reflect . Value , visit func ( field reflect . StructField , val reflect . Value , owner reflect . Type ) bool ) { t := v . Type ( ) for i := 0 ; i < t . NumField ( ) ; i ++ { field := t . Field ( i ) val := v . Field ( i ) expand := visit ( field , val , t ) if expand && field . Type . Kind ( ) == reflect . Struct { walkFields ( val , visit ) } } }

// walkFields calls a function for each field of a struct, recursively expanding struct fields.

walkFields calls a function for each field of a struct recursively expanding struct fields .


func (p *Parser) Parse(args []string) error {
	// If -h or --help were specified then print usage
	for _, arg := range args {
		if arg == "-h" || arg == "--help" {
			return ErrHelp
		}
		if arg == "--version" {
			return ErrVersion
		}
		if arg == "--" {
			break
		}
	}

	// Process all command line arguments
	return process(p.specs, args)
}

// Parse processes the given command line option, storing the results in the field
// of the structs from which NewParser was constructed

Parse processes the given command line option storing the results in the field of the structs from which NewParser was constructed


func setSlice(dest reflect.Value, values []string, trunc bool) error {
	if !dest.CanSet() {
		return fmt.Errorf("field is not writable")
	}

	var ptr bool
	elem := dest.Type().Elem()
	if elem.Kind() == reflect.Ptr && !elem.Implements(textUnmarshalerType) {
		ptr = true
		elem = elem.Elem()
	}

	// Truncate the dest slice in case default values exist
	if trunc && !dest.IsNil() {
		dest.SetLen(0)
	}

	for _, s := range values {
		v := reflect.New(elem)
		if err := scalar.ParseValue(v.Elem(), s); err != nil {
			return err
		}
		if !ptr {
			v = v.Elem()
		}
		dest.Set(reflect.Append(dest, v))
	}
	return nil
}

// parse a value as the appropriate type and store it in the struct


func canParse(t reflect.Type) (parseable, boolean, multiple bool) {
	parseable = scalar.CanParse(t)
	boolean = isBoolean(t)
	if parseable {
		return
	}

	// Look inside pointer types
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	// Look inside slice types
	if t.Kind() == reflect.Slice {
		multiple = true
		t = t.Elem()
	}

	parseable = scalar.CanParse(t)
	boolean = isBoolean(t)
	if parseable {
		return
	}

	// Look inside pointer types (again, in case of []*Type)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	parseable = scalar.CanParse(t)
	boolean = isBoolean(t)
	if parseable {
		return
	}

	return false, false, false
}

// canParse returns true if the type can be parsed from a string


func isBoolean(t reflect.Type) bool {
	switch {
	case t.Implements(textUnmarshalerType):
		return false
	case t.Kind() == reflect.Bool:
		return true
	case t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Bool:
		return true
	default:
		return false
	}
}

func isBoolean ( t reflect . Type ) bool { switch { case t . Implements ( textUnmarshalerType ) : return false case t . Kind ( ) == reflect . Bool : return true case t . Kind ( ) == reflect . Ptr && t . Elem ( ) . Kind ( ) == reflect . Bool : return true default : return false } }

// isBoolean returns true if the type can be parsed from a single string


func NewFromMap(m map[string]interface{}) *Tree {
	t := &Tree{root: &node{}}
	for k, v := range m {
		t.Insert(k, v)
	}
	return t
}

func NewFromMap ( m map [ string ] interface { } ) * Tree { t := & Tree { root : & node { } } for k , v := range m { t . Insert ( k , v ) } return t }

// NewFromMap returns a new tree containing the keys
// from an existing map

NewFromMap returns a new tree containing the keys from an existing map


func (t *Tree) Insert(s string, v interface{}) (interface{}, bool) {
	var parent *node
	n := t.root
	search := s
	for {
		// Handle key exhaution
		if len(search) == 0 {
			if n.isLeaf() {
				old := n.leaf.val
				n.leaf.val = v
				return old, true
			}

			n.leaf = &leafNode{
				key: s,
				val: v,
			}
			t.size++
			return nil, false
		}

		// Look for the edge
		parent = n
		n = n.getEdge(search[0])

		// No edge, create one
		if n == nil {
			e := edge{
				label: search[0],
				node: &node{
					leaf: &leafNode{
						key: s,
						val: v,
					},
					prefix: search,
				},
			}
			parent.addEdge(e)
			t.size++
			return nil, false
		}

		// Determine longest prefix of the search key on match
		commonPrefix := longestPrefix(search, n.prefix)
		if commonPrefix == len(n.prefix) {
			search = search[commonPrefix:]
			continue
		}

		// Split the node
		t.size++
		child := &node{
			prefix: search[:commonPrefix],
		}
		parent.updateEdge(search[0], child)

		// Restore the existing node
		child.addEdge(edge{
			label: n.prefix[commonPrefix],
			node:  n,
		})
		n.prefix = n.prefix[commonPrefix:]

		// Create a new leaf node
		leaf := &leafNode{
			key: s,
			val: v,
		}

		// If the new key is a subset, add to to this node
		search = search[commonPrefix:]
		if len(search) == 0 {
			child.leaf = leaf
			return nil, false
		}

		// Create a new edge for the node
		child.addEdge(edge{
			label: search[0],
			node: &node{
				leaf:   leaf,
				prefix: search,
			},
		})
		return nil, false
	}
}

// Insert is used to add a newentry or update
// an existing entry. Returns if updated.

Insert is used to add a newentry or update an existing entry . Returns if updated .


func (t *Tree) Delete(s string) (interface{}, bool) {
	var parent *node
	var label byte
	n := t.root
	search := s
	for {
		// Check for key exhaution
		if len(search) == 0 {
			if !n.isLeaf() {
				break
			}
			goto DELETE
		}

		// Look for an edge
		parent = n
		label = search[0]
		n = n.getEdge(label)
		if n == nil {
			break
		}

		// Consume the search prefix
		if strings.HasPrefix(search, n.prefix) {
			search = search[len(n.prefix):]
		} else {
			break
		}
	}
	return nil, false

DELETE:
	// Delete the leaf
	leaf := n.leaf
	n.leaf = nil
	t.size--

	// Check if we should delete this node from the parent
	if parent != nil && len(n.edges) == 0 {
		parent.delEdge(label)
	}

	// Check if we should merge this node
	if n != t.root && len(n.edges) == 1 {
		n.mergeChild()
	}

	// Check if we should merge the parent's other child
	if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() {
		parent.mergeChild()
	}

	return leaf.val, true
}

// Delete is used to delete a key, returning the previous
// value and if it was deleted

Delete is used to delete a key returning the previous value and if it was deleted


func (t *Tree) DeletePrefix(s string) int {
	return t.deletePrefix(nil, t.root, s)
}

func ( t * Tree ) DeletePrefix ( s string ) int { return t . deletePrefix ( nil , t . root , s ) }

// DeletePrefix is used to delete the subtree under a prefix
// Returns how many nodes were deleted
// Use this to delete large subtrees efficiently

DeletePrefix is used to delete the subtree under a prefix Returns how many nodes were deleted Use this to delete large subtrees efficiently


func (t *Tree) deletePrefix(parent, n *node, prefix string) int {
	// Check for key exhaustion
	if len(prefix) == 0 {
		// Remove the leaf node
		subTreeSize := 0
		//recursively walk from all edges of the node to be deleted
		recursiveWalk(n, func(s string, v interface{}) bool {
			subTreeSize++
			return false
		})
		if n.isLeaf() {
			n.leaf = nil
		}
		n.edges = nil // deletes the entire subtree

		// Check if we should merge the parent's other child
		if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() {
			parent.mergeChild()
		}
		t.size -= subTreeSize
		return subTreeSize
	}

	// Look for an edge
	label := prefix[0]
	child := n.getEdge(label)
	if child == nil || (!strings.HasPrefix(child.prefix, prefix) && !strings.HasPrefix(prefix, child.prefix)) {
		return 0
	}

	// Consume the search prefix
	if len(child.prefix) > len(prefix) {
		prefix = prefix[len(prefix):]
	} else {
		prefix = prefix[len(child.prefix):]
	}
	return t.deletePrefix(n, child, prefix)
}


func (t *Tree) Get(s string) (interface{}, bool) {
	n := t.root
	search := s
	for {
		// Check for key exhaution
		if len(search) == 0 {
			if n.isLeaf() {
				return n.leaf.val, true
			}
			break
		}

		// Look for an edge
		n = n.getEdge(search[0])
		if n == nil {
			break
		}

		// Consume the search prefix
		if strings.HasPrefix(search, n.prefix) {
			search = search[len(n.prefix):]
		} else {
			break
		}
	}
	return nil, false
}

func
(
t
*
Tree
)
Get
(
s
string
)
(
interface
{
}
,
bool
)
{
n
:=
t
.
root
search
:=
s
for
{
// Check for key exhaution
if
len
(
search
)
==
0
{
if
n
.
isLeaf
(
)
{
return
n
.
leaf
.
val
,
true
}
break
}
// Look for an edge
n
=
n
.
getEdge
(
search
[
0
]
)
if
n
==
{
break
}
// Consume the search prefix
if
strings
.
HasPrefix
(
search
,
n
.
prefix
)
{
search
=
search
[
len
(
n
.
prefix
)
:
]
}
else
{
break
}
}
return
,
false
}

// Get is used to lookup a specific key, returning
// the value and if it was found

Get is used to lookup a specific key returning the value and if it was found


func (t *Tree) LongestPrefix(s string) (string, interface{}, bool) {
	var last *leafNode
	n := t.root
	search := s
	for {
		// Look for a leaf node
		if n.isLeaf() {
			last = n.leaf
		}

		// Check for key exhaution
		if len(search) == 0 {
			break
		}

		// Look for an edge
		n = n.getEdge(search[0])
		if n == nil {
			break
		}

		// Consume the search prefix
		if strings.HasPrefix(search, n.prefix) {
			search = search[len(n.prefix):]
		} else {
			break
		}
	}
	if last != nil {
		return last.key, last.val, true
	}
	return "", nil, false
}

func
(
t
*
Tree
)
LongestPrefix
(
s
string
)
(
string
,
interface
{
}
,
bool
)
{
var
last
*
leafNode
n
:=
t
.
root
search
:=
s
for
{
// Look for a leaf node
if
n
.
isLeaf
(
)
{
last
=
n
.
leaf
}
// Check for key exhaution
if
len
(
search
)
==
0
{
break
}
// Look for an edge
n
=
n
.
getEdge
(
search
[
0
]
)
if
n
==
{
break
}
// Consume the search prefix
if
strings
.
HasPrefix
(
search
,
n
.
prefix
)
{
search
=
search
[
len
(
n
.
prefix
)
:
]
}
else
{
break
}
}
if
last
!=
{
return
last
.
key
,
last
.
val
,
true
}
return
"
"
,
,
false
}

// LongestPrefix is like Get, but instead of an
// exact match, it will return the longest prefix match.

LongestPrefix is like Get but instead of an exact match it will return the longest prefix match .


func (t *Tree) Minimum() (string, interface{}, bool) {
	n := t.root
	for {
		if n.isLeaf() {
			return n.leaf.key, n.leaf.val, true
		}
		if len(n.edges) > 0 {
			n = n.edges[0].node
		} else {
			break
		}
	}
	return "", nil, false
}

func ( t * Tree ) Minimum ( ) ( string , interface { } , bool ) { n := t . root for { if n . isLeaf ( ) { return n . leaf . key , n . leaf . val , true } if len ( n . edges ) > 0 { n = n . edges [ 0 ] . node } else { break } } return " " , nil , false }

// Minimum is used to return the minimum value in the tree


func (t *Tree) WalkPrefix(prefix string, fn WalkFn) {
	n := t.root
	search := prefix
	for {
		// Check for key exhaution
		if len(search) == 0 {
			recursiveWalk(n, fn)
			return
		}

		// Look for an edge
		n = n.getEdge(search[0])
		if n == nil {
			break
		}

		// Consume the search prefix
		if strings.HasPrefix(search, n.prefix) {
			search = search[len(n.prefix):]

		} else if strings.HasPrefix(n.prefix, search) {
			// Child may be under our search prefix
			recursiveWalk(n, fn)
			return
		} else {
			break
		}
	}

}

func
(
t
*
Tree
)
WalkPrefix
(
prefix
string
,
fn
WalkFn
)
{
n
:=
t
.
root
search
:=
prefix
for
{
// Check for key exhaution
if
len
(
search
)
==
0
{
recursiveWalk
(
n
,
fn
)
return
}
// Look for an edge
n
=
n
.
getEdge
(
search
[
0
]
)
if
n
==
{
break
}
// Consume the search prefix
if
strings
.
HasPrefix
(
search
,
n
.
prefix
)
{
search
=
search
[
len
(
n
.
prefix
)
:
]
}
else
if
strings
.
HasPrefix
(
n
.
prefix
,
search
)
{
// Child may be under our search prefix
recursiveWalk
(
n
,
fn
)
return
}
else
{
break
}
}
}

// WalkPrefix is used to walk the tree under a prefix


func recursiveWalk(n *node, fn WalkFn) bool {
	// Visit the leaf values if any
	if n.leaf != nil && fn(n.leaf.key, n.leaf.val) {
		return true
	}

	// Recurse on the children
	for _, e := range n.edges {
		if recursiveWalk(e.node, fn) {
			return true
		}
	}
	return false
}

func
recursiveWalk
(
n
*
node
,
fn
WalkFn
)
bool
{
// Visit the leaf values if any
if
n
.
leaf
!=
&&
fn
(
n
.
leaf
.
key
,
n
.
leaf
.
val
)
{
return
true
}
// Recurse on the children
for
_
,
e
:=
range
n
.
edges
{
if
recursiveWalk
(
e
.
node
,
fn
)
{
return
true
}
}
return
false
}

// recursiveWalk is used to do a pre-order walk of a node
// recursively. Returns true if the walk should be aborted

recursiveWalk is used to do a pre - order walk of a node recursively . Returns true if the walk should be aborted


func (t *Tree) ToMap() map[string]interface{} {
	out := make(map[string]interface{}, t.size)
	t.Walk(func(k string, v interface{}) bool {
		out[k] = v
		return false
	})
	return out
}

func ( t * Tree ) ToMap ( ) map [ string ] interface { } { out := make ( map [ string ] interface { } , t . size ) t . Walk ( func ( k string , v interface { } ) bool { out [ k ] = v return false } ) return out }

// ToMap is used to walk the tree and convert it into a map


func checkip(ip string) (iptype uint32, ipnum *big.Int, ipindex uint32) {
	iptype = 0
	ipnum = big.NewInt(0)
	ipnumtmp := big.NewInt(0)
	ipindex = 0
	ipaddress := net.ParseIP(ip)

	if ipaddress != nil {
		v4 := ipaddress.To4()

		if v4 != nil {
			iptype = 4
			ipnum.SetBytes(v4)
		} else {
			v6 := ipaddress.To16()

			if v6 != nil {
				iptype = 6
				ipnum.SetBytes(v6)
			}
		}
	}
	if iptype == 4 {
		if meta.ipv4indexbaseaddr > 0 {
			ipnumtmp.Rsh(ipnum, 16)
			ipnumtmp.Lsh(ipnumtmp, 3)
			ipindex = uint32(ipnumtmp.Add(ipnumtmp, big.NewInt(int64(meta.ipv4indexbaseaddr))).Uint64())
		}
	} else if iptype == 6 {
		if meta.ipv6indexbaseaddr > 0 {
			ipnumtmp.Rsh(ipnum, 112)
			ipnumtmp.Lsh(ipnumtmp, 3)
			ipindex = uint32(ipnumtmp.Add(ipnumtmp, big.NewInt(int64(meta.ipv6indexbaseaddr))).Uint64())
		}
	}
	return
}

func checkip ( ip string ) ( iptype uint32 , ipnum * big . Int , ipindex uint32 ) { iptype = 0 ipnum = big . NewInt ( 0 ) ipnumtmp := big . NewInt ( 0 ) ipindex = 0 ipaddress := net . ParseIP ( ip ) if ipaddress != nil { v4 := ipaddress . To4 ( ) if v4 != nil { iptype = 4 ipnum . SetBytes ( v4 ) } else { v6 := ipaddress . To16 ( ) if v6 != nil { iptype = 6 ipnum . SetBytes ( v6 ) } } } if iptype == 4 { if meta . ipv4indexbaseaddr > 0 { ipnumtmp . Rsh ( ipnum , 16 ) ipnumtmp . Lsh ( ipnumtmp , 3 ) ipindex = uint32 ( ipnumtmp . Add ( ipnumtmp , big . NewInt ( int64 ( meta . ipv4indexbaseaddr ) ) ) . Uint64 ( ) ) } } else if iptype == 6 { if meta . ipv6indexbaseaddr > 0 { ipnumtmp . Rsh ( ipnum , 112 ) ipnumtmp . Lsh ( ipnumtmp , 3 ) ipindex = uint32 ( ipnumtmp . Add ( ipnumtmp , big . NewInt ( int64 ( meta . ipv6indexbaseaddr ) ) ) . Uint64 ( ) ) } } return }

// get IP type and calculate IP number; calculates index too if exists

get IP type and calculate IP number ; calculates index too if exists


func readuint32(pos uint32) uint32 {
	pos2 := int64(pos)
	var retval uint32
	data := make([]byte, 4)
	_, err := f.ReadAt(data, pos2 - 1)
	if err != nil {
		fmt.Println("File read failed:", err)
	}
	buf := bytes.NewReader(data)
	err = binary.Read(buf, binary.LittleEndian, &retval)
	if err != nil {
		fmt.Println("Binary read failed:", err)
	}
	return retval
}

func readuint32 ( pos uint32 ) uint32 { pos2 := int64 ( pos ) var retval uint32 data := make ( [ ] byte , 4 ) _ , err := f . ReadAt ( data , pos2 - 1 ) if err != nil { fmt . Println ( " " , err ) } buf := bytes . NewReader ( data ) err = binary . Read ( buf , binary . LittleEndian , & retval ) if err != nil { fmt . Println ( " " , err ) } return retval }


func readuint128(pos uint32) *big.Int {
	pos2 := int64(pos)
	retval := big.NewInt(0)
	data := make([]byte, 16)
	_, err := f.ReadAt(data, pos2 - 1)
	if err != nil {
		fmt.Println("File read failed:", err)
	}

	// little endian to big endian
	for i, j := 0, len(data)-1; i < j; i, j = i+1, j-1 {
		data[i], data[j] = data[j], data[i]
	}
	retval.SetBytes(data)
	return retval
}

func
readuint128
(
pos
uint32
)
*
big
.
Int
{
pos2
:=
int64
(
pos
)
retval
:=
big
.
NewInt
(
0
)
data
:=
make
(
[
]
byte
,
16
)
_
,
err
:=
f
.
ReadAt
(
data
,
pos2
1
)
if
err
!=
{
fmt
.
Println
(
"
"
,
err
)
}
// little endian to big endian
for
i
,
j
:=
0
,
len
(
data
)
1
;
i
<
j
;
i
,
j
=
i
+
1
,
j
1
{
data
[
i
]
,
data
[
j
]
=
data
[
j
]
,
data
[
i
]
}
retval
.
SetBytes
(
data
)
return
retval
}


func loadmessage (mesg string) IP2Locationrecord {
	var x IP2Locationrecord

	x.Country_short = mesg
	x.Country_long = mesg
	x.Region = mesg
	x.City = mesg
	x.Isp = mesg
	x.Domain = mesg
	x.Zipcode = mesg
	x.Timezone = mesg
	x.Netspeed = mesg
	x.Iddcode = mesg
	x.Areacode = mesg
	x.Weatherstationcode = mesg
	x.Weatherstationname = mesg
	x.Mcc = mesg
	x.Mnc = mesg
	x.Mobilebrand = mesg
	x.Usagetype = mesg

	return x
}

func loadmessage ( mesg string ) IP2Locationrecord { var x IP2Locationrecord x . Country_short = mesg x . Country_long = mesg x . Region = mesg x . City = mesg x . Isp = mesg x . Domain = mesg x . Zipcode = mesg x . Timezone = mesg x . Netspeed = mesg x . Iddcode = mesg x . Areacode = mesg x . Weatherstationcode = mesg x . Weatherstationname = mesg x . Mcc = mesg x . Mnc = mesg x . Mobilebrand = mesg x . Usagetype = mesg return x }


func Printrecord(x IP2Locationrecord) {
	fmt.Printf("country_short: %s\n", x.Country_short)
	fmt.Printf("country_long: %s\n", x.Country_long)
	fmt.Printf("region: %s\n", x.Region)
	fmt.Printf("city: %s\n", x.City)
	fmt.Printf("isp: %s\n", x.Isp)
	fmt.Printf("latitude: %f\n", x.Latitude)
	fmt.Printf("longitude: %f\n", x.Longitude)
	fmt.Printf("domain: %s\n", x.Domain)
	fmt.Printf("zipcode: %s\n", x.Zipcode)
	fmt.Printf("timezone: %s\n", x.Timezone)
	fmt.Printf("netspeed: %s\n", x.Netspeed)
	fmt.Printf("iddcode: %s\n", x.Iddcode)
	fmt.Printf("areacode: %s\n", x.Areacode)
	fmt.Printf("weatherstationcode: %s\n", x.Weatherstationcode)
	fmt.Printf("weatherstationname: %s\n", x.Weatherstationname)
	fmt.Printf("mcc: %s\n", x.Mcc)
	fmt.Printf("mnc: %s\n", x.Mnc)
	fmt.Printf("mobilebrand: %s\n", x.Mobilebrand)
	fmt.Printf("elevation: %f\n", x.Elevation)
	fmt.Printf("usagetype: %s\n", x.Usagetype)
}

func Printrecord ( x IP2Locationrecord ) { fmt . Printf ( " \n " , x . Country_short ) fmt . Printf ( " \n " , x . Country_long ) fmt . Printf ( " \n " , x . Region ) fmt . Printf ( " \n " , x . City ) fmt . Printf ( " \n " , x . Isp ) fmt . Printf ( " \n " , x . Latitude ) fmt . Printf ( " \n " , x . Longitude ) fmt . Printf ( " \n " , x . Domain ) fmt . Printf ( " \n " , x . Zipcode ) fmt . Printf ( " \n " , x . Timezone ) fmt . Printf ( " \n " , x . Netspeed ) fmt . Printf ( " \n " , x . Iddcode ) fmt . Printf ( " \n " , x . Areacode ) fmt . Printf ( " \n " , x . Weatherstationcode ) fmt . Printf ( " \n " , x . Weatherstationname ) fmt . Printf ( " \n " , x . Mcc ) fmt . Printf ( " \n " , x . Mnc ) fmt . Printf ( " \n " , x . Mobilebrand ) fmt . Printf ( " \n " , x . Elevation ) fmt . Printf ( " \n " , x . Usagetype ) }


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	gc.Save()
	gc.Scale(0.5, 0.5)
	// Draw a (partial) gopher
	Draw(gc)
	gc.Restore()

	// Return the output filename
	return samples.Output("gopher", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
gc
.
Save
(
)
gc
.
Scale
(
0.5
,
0.5
)
// Draw a (partial) gopher
Draw
(
gc
)
gc
.
Restore
(
)
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}

// Main draws a left hand and ear of a gopher. Afterwards it returns
// the filename. This should only be used during testing.

Main draws a left hand and ear of a gopher . Afterwards it returns the filename . This should only be used during testing .


func SaveToPdfFile(filePath string, pdf *gofpdf.Fpdf) error {
	return pdf.OutputFileAndClose(filePath)
}

func SaveToPdfFile ( filePath string , pdf * gofpdf . Fpdf ) error { return pdf . OutputFileAndClose ( filePath ) }

// SaveToPdfFile creates and saves a pdf document to a file


func (p *Path) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
	if len(p.Components) == 0 { //special case when no move has been done
		p.MoveTo(x, y)
	} else {
		p.appendToPath(CubicCurveToCmp, cx1, cy1, cx2, cy2, x, y)
	}
	p.x = x
	p.y = y
}

// CubicCurveTo adds a cubic bezier curve to the current path


func (p *Path) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
	endAngle := startAngle + angle
	clockWise := true
	if angle < 0 {
		clockWise = false
	}
	// normalize
	if clockWise {
		for endAngle < startAngle {
			endAngle += math.Pi * 2.0
		}
	} else {
		for startAngle < endAngle {
			startAngle += math.Pi * 2.0
		}
	}
	startX := cx + math.Cos(startAngle)*rx
	startY := cy + math.Sin(startAngle)*ry
	if len(p.Components) > 0 {
		p.LineTo(startX, startY)
	} else {
		p.MoveTo(startX, startY)
	}
	p.appendToPath(ArcToCmp, cx, cy, rx, ry, startAngle, angle)
	p.x = cx + math.Cos(endAngle)*rx
	p.y = cy + math.Sin(endAngle)*ry
}

func
(
p
*
Path
)
ArcTo
(
cx
,
cy
,
rx
,
ry
,
startAngle
,
angle
float64
)
{
endAngle
:=
startAngle
+
angle
clockWise
:=
true
if
angle
<
0
{
clockWise
=
false
}
// normalize
if
clockWise
{
for
endAngle
<
startAngle
{
endAngle
+=
math
.
Pi
*
2.0
}
}
else
{
for
startAngle
<
endAngle
{
startAngle
+=
math
.
Pi
*
2.0
}
}
startX
:=
cx
+
math
.
Cos
(
startAngle
)
*
rx
startY
:=
cy
+
math
.
Sin
(
startAngle
)
*
ry
if
len
(
p
.
Components
)
>
0
{
p
.
LineTo
(
startX
,
startY
)
}
else
{
p
.
MoveTo
(
startX
,
startY
)
}
p
.
appendToPath
(
ArcToCmp
,
cx
,
cy
,
rx
,
ry
,
startAngle
,
angle
)
p
.
x
=
cx
+
math
.
Cos
(
endAngle
)
*
rx
p
.
y
=
cy
+
math
.
Sin
(
endAngle
)
*
ry
}


func (p *Path) String() string {
	s := ""
	j := 0
	for _, cmd := range p.Components {
		switch cmd {
		case MoveToCmp:
			s += fmt.Sprintf("MoveTo: %f, %f\n", p.Points[j], p.Points[j+1])
			j = j + 2
		case LineToCmp:
			s += fmt.Sprintf("LineTo: %f, %f\n", p.Points[j], p.Points[j+1])
			j = j + 2
		case QuadCurveToCmp:
			s += fmt.Sprintf("QuadCurveTo: %f, %f, %f, %f\n", p.Points[j], p.Points[j+1], p.Points[j+2], p.Points[j+3])
			j = j + 4
		case CubicCurveToCmp:
			s += fmt.Sprintf("CubicCurveTo: %f, %f, %f, %f, %f, %f\n", p.Points[j], p.Points[j+1], p.Points[j+2], p.Points[j+3], p.Points[j+4], p.Points[j+5])
			j = j + 6
		case ArcToCmp:
			s += fmt.Sprintf("ArcTo: %f, %f, %f, %f, %f, %f\n", p.Points[j], p.Points[j+1], p.Points[j+2], p.Points[j+3], p.Points[j+4], p.Points[j+5])
			j = j + 6
		case CloseCmp:
			s += "Close\n"
		}
	}
	return s
}

func ( p * Path ) String ( ) string { s := " " j := 0 for _ , cmd := range p . Components { switch cmd { case MoveToCmp : s += fmt . Sprintf ( " \n " , p . Points [ j ] , p . Points [ j + 1 ] ) j = j + 2 case LineToCmp : s += fmt . Sprintf ( " \n " , p . Points [ j ] , p . Points [ j + 1 ] ) j = j + 2 case QuadCurveToCmp : s += fmt . Sprintf ( " \n " , p . Points [ j ] , p . Points [ j + 1 ] , p . Points [ j + 2 ] , p . Points [ j + 3 ] ) j = j + 4 case CubicCurveToCmp : s += fmt . Sprintf ( " \n " , p . Points [ j ] , p . Points [ j + 1 ] , p . Points [ j + 2 ] , p . Points [ j + 3 ] , p . Points [ j + 4 ] , p . Points [ j + 5 ] ) j = j + 6 case ArcToCmp : s += fmt . Sprintf ( " \n " , p . Points [ j ] , p . Points [ j + 1 ] , p . Points [ j + 2 ] , p . Points [ j + 3 ] , p . Points [ j + 4 ] , p . Points [ j + 5 ] ) j = j + 6 case CloseCmp : s += " \n " } } return s }

// String returns a debug text view of the path


func (path *Path) VerticalFlip() *Path {
	p := path.Copy()
	j := 0
	for _, cmd := range p.Components {
		switch cmd {
		case MoveToCmp, LineToCmp:
			p.Points[j+1] = -p.Points[j+1]
			j = j + 2
		case QuadCurveToCmp:
			p.Points[j+1] = -p.Points[j+1]
			p.Points[j+3] = -p.Points[j+3]
			j = j + 4
		case CubicCurveToCmp:
			p.Points[j+1] = -p.Points[j+1]
			p.Points[j+3] = -p.Points[j+3]
			p.Points[j+5] = -p.Points[j+5]
			j = j + 6
		case ArcToCmp:
			p.Points[j+1] = -p.Points[j+1]
			p.Points[j+3] = -p.Points[j+3]
			p.Points[j+4] = -p.Points[j+4] // start angle
			p.Points[j+5] = -p.Points[j+5] // angle
			j = j + 6
		case CloseCmp:
		}
	}
	p.y = -p.y
	return p
}

func
(
path
*
Path
)
VerticalFlip
(
)
*
Path
{
p
:=
path
.
Copy
(
)
j
:=
0
for
_
,
cmd
:=
range
p
.
Components
{
switch
cmd
{
case
MoveToCmp
,
LineToCmp
:
p
.
Points
[
j
+
1
]
=
p
.
Points
[
j
+
1
]
j
=
j
+
2
case
QuadCurveToCmp
:
p
.
Points
[
j
+
1
]
=
p
.
Points
[
j
+
1
]
p
.
Points
[
j
+
3
]
=
p
.
Points
[
j
+
3
]
j
=
j
+
4
case
CubicCurveToCmp
:
p
.
Points
[
j
+
1
]
=
p
.
Points
[
j
+
1
]
p
.
Points
[
j
+
3
]
=
p
.
Points
[
j
+
3
]
p
.
Points
[
j
+
5
]
=
p
.
Points
[
j
+
5
]
j
=
j
+
6
case
ArcToCmp
:
p
.
Points
[
j
+
1
]
=
p
.
Points
[
j
+
1
]
p
.
Points
[
j
+
3
]
=
p
.
Points
[
j
+
3
]
p
.
Points
[
j
+
4
]
=
p
.
Points
[
j
+
4
]
// start angle
p
.
Points
[
j
+
5
]
=
p
.
Points
[
j
+
5
]
// angle
j
=
j
+
6
case
CloseCmp
:
}
}
p
.
y
=
p
.
y
return
p
}


func NewGlyphCache() *GlyphCacheImp {
	glyphs := make(map[string]map[rune]*Glyph)
	return &GlyphCacheImp {
		glyphs: glyphs,
	}
}

func NewGlyphCache ( ) * GlyphCacheImp { glyphs := make ( map [ string ] map [ rune ] * Glyph ) return & GlyphCacheImp { glyphs : glyphs , } }

// NewGlyphCache initializes a GlyphCache


func (glyphCache *GlyphCacheImp) Fetch(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph {
	if glyphCache.glyphs[fontName] == nil {
		glyphCache.glyphs[fontName] = make(map[rune]*Glyph, 60)
	}
	if glyphCache.glyphs[fontName][chr] == nil {
		glyphCache.glyphs[fontName][chr] = renderGlyph(gc, fontName, chr)
	}
	return glyphCache.glyphs[fontName][chr].Copy()
}

func ( glyphCache * GlyphCacheImp ) Fetch ( gc draw2d . GraphicContext , fontName string , chr rune ) * Glyph { if glyphCache . glyphs [ fontName ] == nil { glyphCache . glyphs [ fontName ] = make ( map [ rune ] * Glyph , 60 ) } if glyphCache . glyphs [ fontName ] [ chr ] == nil { glyphCache . glyphs [ fontName ] [ chr ] = renderGlyph ( gc , fontName , chr ) } return glyphCache . glyphs [ fontName ] [ chr ] . Copy ( ) }

// Fetch fetches a glyph from the cache, calling renderGlyph first if it doesn't already exist

Fetch fetches a glyph from the cache calling renderGlyph first if it doesn t already exist


func renderGlyph(gc draw2d.GraphicContext, fontName string, chr rune) *Glyph {
	gc.Save()
	defer gc.Restore()
	gc.BeginPath()
	width := gc.CreateStringPath(string(chr), 0, 0)
	path := gc.GetPath()
	return &Glyph{
		Path:  &path,
		Width: width,
	}
}

func renderGlyph ( gc draw2d . GraphicContext , fontName string , chr rune ) * Glyph { gc . Save ( ) defer gc . Restore ( ) gc . BeginPath ( ) width := gc . CreateStringPath ( string ( chr ) , 0 , 0 ) path := gc . GetPath ( ) return & Glyph { Path : & path , Width : width , } }

// renderGlyph renders a glyph then caches and returns it


func (g *Glyph) Copy() *Glyph {
	return &Glyph{
		Path:  g.Path.Copy(),
		Width: g.Width,
	}
}

func ( g * Glyph ) Copy ( ) * Glyph { return & Glyph { Path : g . Path . Copy ( ) , Width : g . Width , } }


func (g *Glyph) Fill(gc draw2d.GraphicContext, x, y float64) float64 {
	gc.Save()
	gc.BeginPath()
	gc.Translate(x, y)
	gc.Fill(g.Path)
	gc.Restore()
	return g.Width
}

func ( g * Glyph ) Fill ( gc draw2d . GraphicContext , x , y float64 ) float64 { gc . Save ( ) gc . BeginPath ( ) gc . Translate ( x , y ) gc . Fill ( g . Path ) gc . Restore ( ) return g . Width }

// Fill copies a glyph from the cache, and fills it

Fill copies a glyph from the cache and fills it


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	gc.SetFillRule(draw2d.FillRuleWinding)
	gc.Clear()
	// Draw the line
	for x := 5.0; x < 297; x += 10 {
		Draw(gc, x, 0, x, 210)
	}
	gc.ClearRect(100, 75, 197, 135)
	draw2dkit.Ellipse(gc, 148.5, 105, 35, 25)
	gc.SetFillColor(color.RGBA{0xff, 0xff, 0x44, 0xff})
	gc.FillStroke()

	// Return the output filename
	return samples.Output("line", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
gc
.
SetFillRule
(
draw2d
.
FillRuleWinding
)
gc
.
Clear
(
)
// Draw the line
for
x
:=
5.0
;
x
<
297
;
x
+=
10
{
Draw
(
gc
,
x
,
0
,
x
,
210
)
}
gc
.
ClearRect
(
100
,
75
,
197
,
135
)
draw2dkit
.
Ellipse
(
gc
,
148.5
,
105
,
35
,
25
)
gc
.
SetFillColor
(
color
.
RGBA
{
0xff
,
0xff
,
0x44
,
0xff
}
)
gc
.
FillStroke
(
)
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}

// Main draws vertically spaced lines and returns the filename.
// This should only be used during testing.

Main draws vertically spaced lines and returns the filename . This should only be used during testing .


func Draw(gc draw2d.GraphicContext, x0, y0, x1, y1 float64) {
	// Draw a line
	gc.MoveTo(x0, y0)
	gc.LineTo(x1, y1)
	gc.Stroke()
}

func
Draw
(
gc
draw2d
.
GraphicContext
,
x0
,
y0
,
x1
,
y1
float64
)
{
// Draw a line
gc
.
MoveTo
(
x0
,
y0
)
gc
.
LineTo
(
x1
,
y1
)
gc
.
Stroke
(
)
}


func (p *Painter) Paint(ss []raster.Span, done bool) {
	//gl.Begin(gl.LINES)
	sslen := len(ss)
	clenrequired := sslen * 8
	vlenrequired := sslen * 4
	if clenrequired >= (cap(p.colors) - len(p.colors)) {
		p.Flush()

		if clenrequired >= cap(p.colors) {
			p.vertices = make([]int32, 0, vlenrequired+(vlenrequired/2))
			p.colors = make([]uint8, 0, clenrequired+(clenrequired/2))
		}
	}
	vi := len(p.vertices)
	ci := len(p.colors)
	p.vertices = p.vertices[0 : vi+vlenrequired]
	p.colors = p.colors[0 : ci+clenrequired]
	var (
		colors   []uint8
		vertices []int32
	)
	for _, s := range ss {
		a := uint8((s.Alpha * p.ca / M16) >> 8)

		colors = p.colors[ci:]
		colors[0] = p.cr
		colors[1] = p.cg
		colors[2] = p.cb
		colors[3] = a
		colors[4] = p.cr
		colors[5] = p.cg
		colors[6] = p.cb
		colors[7] = a
		ci += 8
		vertices = p.vertices[vi:]
		vertices[0] = int32(s.X0)
		vertices[1] = int32(s.Y)
		vertices[2] = int32(s.X1)
		vertices[3] = int32(s.Y)
		vi += 4
	}
}

func ( p * Painter ) Paint ( ss [ ] raster . Span , done bool ) { //gl.Begin(gl.LINES) sslen := len ( ss ) clenrequired := sslen * 8 vlenrequired := sslen * 4 if clenrequired >= ( cap ( p . colors ) - len ( p . colors ) ) { p . Flush ( ) if clenrequired >= cap ( p . colors ) { p . vertices = make ( [ ] int32 , 0 , vlenrequired + ( vlenrequired / 2 ) ) p . colors = make ( [ ] uint8 , 0 , clenrequired + ( clenrequired / 2 ) ) } } vi := len ( p . vertices ) ci := len ( p . colors ) p . vertices = p . vertices [ 0 : vi + vlenrequired ] p . colors = p . colors [ 0 : ci + clenrequired ] var ( colors [ ] uint8 vertices [ ] int32 ) for _ , s := range ss { a := uint8 ( ( s . Alpha * p . ca / M16 ) >> 8 ) colors = p . colors [ ci : ] colors [ 0 ] = p . cr colors [ 1 ] = p . cg colors [ 2 ] = p . cb colors [ 3 ] = a colors [ 4 ] = p . cr colors [ 5 ] = p . cg colors [ 6 ] = p . cb colors [ 7 ] = a ci += 8 vertices = p . vertices [ vi : ] vertices [ 0 ] = int32 ( s . X0 ) vertices [ 1 ] = int32 ( s . Y ) vertices [ 2 ] = int32 ( s . X1 ) vertices [ 3 ] = int32 ( s . Y ) vi += 4 } }

// Paint satisfies the Painter interface by painting ss onto an image.RGBA.

Paint satisfies the Painter interface by painting ss onto an image . RGBA .


func (p *Painter) SetColor(c color.Color) {
	r, g, b, a := c.RGBA()
	if a == 0 {
		p.cr = 0
		p.cg = 0
		p.cb = 0
		p.ca = a
	} else {
		p.cr = uint8((r * M16 / a) >> 8)
		p.cg = uint8((g * M16 / a) >> 8)
		p.cb = uint8((b * M16 / a) >> 8)
		p.ca = a
	}
}

func ( p * Painter ) SetColor ( c color . Color ) { r , g , b , a := c . RGBA ( ) if a == 0 { p . cr = 0 p . cg = 0 p . cb = 0 p . ca = a } else { p . cr = uint8 ( ( r * M16 / a ) >> 8 ) p . cg = uint8 ( ( g * M16 / a ) >> 8 ) p . cb = uint8 ( ( b * M16 / a ) >> 8 ) p . ca = a } }

// SetColor sets the color to paint the spans.

SetColor sets the color to paint the spans .


func NewPainter() *Painter {
	p := new(Painter)
	p.vertices = make([]int32, 0, 1024)
	p.colors = make([]uint8, 0, 1024)
	return p
}

func NewPainter ( ) * Painter { p := new ( Painter ) p . vertices = make ( [ ] int32 , 0 , 1024 ) p . colors = make ( [ ] uint8 , 0 , 1024 ) return p }

// NewRGBAPainter creates a new RGBAPainter for the given image.

NewRGBAPainter creates a new RGBAPainter for the given image .


func (gc *GraphicContext) GetStringBounds(s string) (left, top, right, bottom float64) {
	f, err := gc.loadCurrentFont()
	if err != nil {
		log.Println(err)
		return 0, 0, 0, 0
	}
	top, left, bottom, right = 10e6, 10e6, -10e6, -10e6
	cursor := 0.0
	prev, hasPrev := truetype.Index(0), false
	for _, rune := range s {
		index := f.Index(rune)
		if hasPrev {
			cursor += fUnitsToFloat64(f.Kern(fixed.Int26_6(gc.Current.Scale), prev, index))
		}
		if err := gc.glyphBuf.Load(gc.Current.Font, fixed.Int26_6(gc.Current.Scale), index, font.HintingNone); err != nil {
			log.Println(err)
			return 0, 0, 0, 0
		}
		e0 := 0
		for _, e1 := range gc.glyphBuf.Ends {
			ps := gc.glyphBuf.Points[e0:e1]
			for _, p := range ps {
				x, y := pointToF64Point(p)
				top = math.Min(top, y)
				bottom = math.Max(bottom, y)
				left = math.Min(left, x+cursor)
				right = math.Max(right, x+cursor)
			}
		}
		cursor += fUnitsToFloat64(f.HMetric(fixed.Int26_6(gc.Current.Scale), index).AdvanceWidth)
		prev, hasPrev = index, true
	}
	return left, top, right, bottom
}

func ( gc * GraphicContext ) GetStringBounds ( s string ) ( left , top , right , bottom float64 ) { f , err := gc . loadCurrentFont ( ) if err != nil { log . Println ( err ) return 0 , 0 , 0 , 0 } top , left , bottom , right = 10e6 , 10e6 , - 10e6 , - 10e6 cursor := 0.0 prev , hasPrev := truetype . Index ( 0 ) , false for _ , rune := range s { index := f . Index ( rune ) if hasPrev { cursor += fUnitsToFloat64 ( f . Kern ( fixed . Int26_6 ( gc . Current . Scale ) , prev , index ) ) } if err := gc . glyphBuf . Load ( gc . Current . Font , fixed . Int26_6 ( gc . Current . Scale ) , index , font . HintingNone ) ; err != nil { log . Println ( err ) return 0 , 0 , 0 , 0 } e0 := 0 for _ , e1 := range gc . glyphBuf . Ends { ps := gc . glyphBuf . Points [ e0 : e1 ] for _ , p := range ps { x , y := pointToF64Point ( p ) top = math . Min ( top , y ) bottom = math . Max ( bottom , y ) left = math . Min ( left , x + cursor ) right = math . Max ( right , x + cursor ) } } cursor += fUnitsToFloat64 ( f . HMetric ( fixed . Int26_6 ( gc . Current . Scale ) , index ) . AdvanceWidth ) prev , hasPrev = index , true } return left , top , right , bottom }

// GetStringBounds returns the approximate pixel bounds of the string s at x, y.
// The the left edge of the em square of the first character of s
// and the baseline intersect at 0, 0 in the returned coordinates.
// Therefore the top and left coordinates may well be negative.

GetStringBounds returns the approximate pixel bounds of the string s at x y . The the left edge of the em square of the first character of s and the baseline intersect at 0 0 in the returned coordinates . Therefore the top and left coordinates may well be negative .


func (gc *GraphicContext) recalc() {
	gc.Current.Scale = gc.Current.FontSize * float64(gc.DPI) * (64.0 / 72.0)
}

func ( gc * GraphicContext ) recalc ( ) { gc . Current . Scale = gc . Current . FontSize * float64 ( gc . DPI ) * ( 64.0 / 72.0 ) }

// recalc recalculates scale and bounds values from the font size, screen
// resolution and font metrics, and invalidates the glyph cache.

recalc recalculates scale and bounds values from the font size screen resolution and font metrics and invalidates the glyph cache .


func (gc *GraphicContext) SetFont(font *truetype.Font) {
	gc.Current.Font = font
}

func ( gc * GraphicContext ) SetFont ( font * truetype . Font ) { gc . Current . Font = font }

// SetFont sets the font used to draw text.

SetFont sets the font used to draw text .


func (gc *GraphicContext) ClearRect(x1, y1, x2, y2 int) {
	mask := gc.newMask(x1, y1, x2-x1, y2-y1)

	newGroup := &Group{
		Groups: gc.svg.Groups,
		Mask:   "url(#" + mask.Id + ")",
	}

	// replace groups with new masked group
	gc.svg.Groups = []*Group{newGroup}
}

func
(
gc
*
GraphicContext
)
ClearRect
(
x1
,
y1
,
x2
,
y2
int
)
{
mask
:=
gc
.
newMask
(
x1
,
y1
,
x2
x1
,
y2
y1
)
newGroup
:=
&
Group
{
Groups
:
gc
.
svg
.
Groups
,
Mask
:
"
"
+
mask
.
Id
+
"
"
,
}
// replace groups with new masked group
gc
.
svg
.
Groups
=
[
]
*
Group
{
newGroup
}
}

// ClearRect fills the specified rectangle with a default transparent color


func (gc *GraphicContext) drawString(text string, drawType drawType, x, y float64) float64 {
	switch gc.svg.FontMode {
	case PathFontMode:
		w := gc.CreateStringPath(text, x, y)
		gc.drawPaths(drawType)
		gc.Current.Path.Clear()
		return w
	case SvgFontMode:
		gc.embedSvgFont(text)
	}

	// create elements
	svgText := Text{}
	group := gc.newGroup(drawType)

	// set attrs to text element
	svgText.Text = text
	svgText.FontSize = gc.Current.FontSize
	svgText.X = x
	svgText.Y = y
	svgText.FontFamily = gc.Current.FontData.Name

	// attach to group
	group.Texts = []*Text{&svgText}
	left, _, right, _ := gc.GetStringBounds(text)
	return right - left
}

func
(
gc
*
GraphicContext
)
drawString
(
text
string
,
drawType
drawType
,
x
,
y
float64
)
float64
{
switch
gc
.
svg
.
FontMode
{
case
PathFontMode
:
w
:=
gc
.
CreateStringPath
(
text
,
x
,
y
)
gc
.
drawPaths
(
drawType
)
gc
.
Current
.
Path
.
Clear
(
)
return
w
case
SvgFontMode
:
gc
.
embedSvgFont
(
text
)
}
// create elements
svgText
:=
Text
{
}
group
:=
gc
.
newGroup
(
drawType
)
// set attrs to text element
svgText
.
Text
=
text
svgText
.
FontSize
=
gc
.
Current
.
FontSize
svgText
.
X
=
x
svgText
.
Y
=
y
svgText
.
FontFamily
=
gc
.
Current
.
FontData
.
Name
// attach to group
group
.
Texts
=
[
]
*
Text
{
&
svgText
}
left
,
_
,
right
,
_
:=
gc
.
GetStringBounds
(
text
)
return
right
left
}

// Add text element to svg and returns its expected width


func (gc *GraphicContext) newGroup(drawType drawType) *Group {
	group := Group{}
	// set attrs to group
	if drawType&stroked == stroked {
		group.Stroke = toSvgRGBA(gc.Current.StrokeColor)
		group.StrokeWidth = toSvgLength(gc.Current.LineWidth)
		group.StrokeLinecap = gc.Current.Cap.String()
		group.StrokeLinejoin = gc.Current.Join.String()
		if len(gc.Current.Dash) > 0 {
			group.StrokeDasharray = toSvgArray(gc.Current.Dash)
			group.StrokeDashoffset = toSvgLength(gc.Current.DashOffset)
		}
	}

	if drawType&filled == filled {
		group.Fill = toSvgRGBA(gc.Current.FillColor)
		group.FillRule = toSvgFillRule(gc.Current.FillRule)
	}

	group.Transform = toSvgTransform(gc.Current.Tr)

	// attach
	gc.svg.Groups = append(gc.svg.Groups, &group)

	return &group
}

func
(
gc
*
GraphicContext
)
newGroup
(
drawType
drawType
)
*
Group
{
group
:=
Group
{
}
// set attrs to group
if
drawType
&
stroked
==
stroked
{
group
.
Stroke
=
toSvgRGBA
(
gc
.
Current
.
StrokeColor
)
group
.
StrokeWidth
=
toSvgLength
(
gc
.
Current
.
LineWidth
)
group
.
StrokeLinecap
=
gc
.
Current
.
Cap
.
String
(
)
group
.
StrokeLinejoin
=
gc
.
Current
.
Join
.
String
(
)
if
len
(
gc
.
Current
.
Dash
)
>
0
{
group
.
StrokeDasharray
=
toSvgArray
(
gc
.
Current
.
Dash
)
group
.
StrokeDashoffset
=
toSvgLength
(
gc
.
Current
.
DashOffset
)
}
}
if
drawType
&
filled
==
filled
{
group
.
Fill
=
toSvgRGBA
(
gc
.
Current
.
FillColor
)
group
.
FillRule
=
toSvgFillRule
(
gc
.
Current
.
FillRule
)
}
group
.
Transform
=
toSvgTransform
(
gc
.
Current
.
Tr
)
// attach
gc
.
svg
.
Groups
=
append
(
gc
.
svg
.
Groups
,
&
group
)
return
&
group
}

// Creates new group from current context
// attach it to svg and return

Creates new group from current context attach it to svg and return


func (gc *GraphicContext) newMask(x, y, width, height int) *Mask {
	mask := &Mask{}
	mask.X = float64(x)
	mask.Y = float64(y)
	mask.Width = toSvgLength(float64(width))
	mask.Height = toSvgLength(float64(height))

	// attach mask
	gc.svg.Masks = append(gc.svg.Masks, mask)
	mask.Id = "mask-" + strconv.Itoa(len(gc.svg.Masks))
	return mask
}

func
(
gc
*
GraphicContext
)
newMask
(
x
,
y
,
width
,
height
int
)
*
Mask
{
mask
:=
&
Mask
{
}
mask
.
X
=
float64
(
x
)
mask
.
Y
=
float64
(
y
)
mask
.
Width
=
toSvgLength
(
float64
(
width
)
)
mask
.
Height
=
toSvgLength
(
float64
(
height
)
)
// attach mask
gc
.
svg
.
Masks
=
append
(
gc
.
svg
.
Masks
,
mask
)
mask
.
Id
=
"
"
+
strconv
.
Itoa
(
len
(
gc
.
svg
.
Masks
)
)
return
mask
}


func (gc *GraphicContext) embedSvgFont(text string) *Font {
	fontName := gc.Current.FontData.Name
	gc.loadCurrentFont()

	// find or create font Element
	svgFont := (*Font)(nil)
	for _, font := range gc.svg.Fonts {
		if font.Name == fontName {
			svgFont = font
			break
		}
	}
	if svgFont == nil {
		// create new
		svgFont = &Font{}
		// and attach
		gc.svg.Fonts = append(gc.svg.Fonts, svgFont)
	}

	// fill with glyphs

	gc.Save()
	defer gc.Restore()
	gc.SetFontSize(2048)
	defer gc.SetDPI(gc.GetDPI())
	gc.SetDPI(92)
filling:
	for _, rune := range text {
		for _, g := range svgFont.Glyphs {
			if g.Rune == Rune(rune) {
				continue filling
			}
		}
		glyph := gc.glyphCache.Fetch(gc, gc.GetFontName(), rune)
		// glyphCache.Load indirectly calls CreateStringPath for single rune string

		glypPath := glyph.Path.VerticalFlip() // svg font glyphs have oposite y axe
		svgFont.Glyphs = append(svgFont.Glyphs, &Glyph{
			Rune:      Rune(rune),
			Desc:      toSvgPathDesc(glypPath),
			HorizAdvX: glyph.Width,
		})
	}

	// set attrs
	svgFont.Id = "font-" + strconv.Itoa(len(gc.svg.Fonts))
	svgFont.Name = fontName

	// TODO use css @font-face with id instead of this
	svgFont.Face = &Face{Family: fontName, Units: 2048, HorizAdvX: 2048}
	return svgFont
}

// Embed svg font definition to svg tree itself
// Or update existing if already exists for curent font data

Embed svg font definition to svg tree itself Or update existing if already exists for curent font data


func TraceQuad(t Liner, quad []float64, flatteningThreshold float64) error {
	if len(quad) < 6 {
		return errors.New("quad length must be >= 6")
	}
	// Allocates curves stack
	var curves [CurveRecursionLimit * 6]float64
	copy(curves[0:6], quad[0:6])
	i := 0
	// current curve
	var c []float64
	var dx, dy, d float64

	for i >= 0 {
		c = curves[i:]
		dx = c[4] - c[0]
		dy = c[5] - c[1]

		d = math.Abs(((c[2]-c[4])*dy - (c[3]-c[5])*dx))

		// if it's flat then trace a line
		if (d*d) <= flatteningThreshold*(dx*dx+dy*dy) || i == len(curves)-6 {
			t.LineTo(c[4], c[5])
			i -= 6
		} else {
			// second half of bezier go lower onto the stack
			SubdivideQuad(c, curves[i+6:], curves[i:])
			i += 6
		}
	}
	return nil
}

// TraceQuad generate lines subdividing the curve using a Liner
// flattening_threshold helps determines the flattening expectation of the curve

TraceQuad generate lines subdividing the curve using a Liner flattening_threshold helps determines the flattening expectation of the curve


func (cs *ContextStack) GetFontName() string {
	fontData := cs.FontData
	return fmt.Sprintf("%s:%d:%d:%9.2f", fontData.Name, fontData.Family, fontData.Style, cs.FontSize)
}

func ( cs * ContextStack ) GetFontName ( ) string { fontData := cs . FontData return fmt . Sprintf ( " " , fontData . Name , fontData . Family , fontData . Style , cs . FontSize ) }

// GetFontName gets the current FontData with fontSize as a string


func NewStackGraphicContext() *StackGraphicContext {
	gc := &StackGraphicContext{}
	gc.Current = new(ContextStack)
	gc.Current.Tr = draw2d.NewIdentityMatrix()
	gc.Current.Path = new(draw2d.Path)
	gc.Current.LineWidth = 1.0
	gc.Current.StrokeColor = image.Black
	gc.Current.FillColor = image.White
	gc.Current.Cap = draw2d.RoundCap
	gc.Current.FillRule = draw2d.FillRuleEvenOdd
	gc.Current.Join = draw2d.RoundJoin
	gc.Current.FontSize = 10
	gc.Current.FontData = DefaultFontData
	return gc
}

func NewStackGraphicContext ( ) * StackGraphicContext { gc := & StackGraphicContext { } gc . Current = new ( ContextStack ) gc . Current . Tr = draw2d . NewIdentityMatrix ( ) gc . Current . Path = new ( draw2d . Path ) gc . Current . LineWidth = 1.0 gc . Current . StrokeColor = image . Black gc . Current . FillColor = image . White gc . Current . Cap = draw2d . RoundCap gc . Current . FillRule = draw2d . FillRuleEvenOdd gc . Current . Join = draw2d . RoundJoin gc . Current . FontSize = 10 gc . Current . FontData = DefaultFontData return gc }

/**
 * Create a new Graphic context from an image
 */


func NewFolderFontCache(folder string) *FolderFontCache {
	return &FolderFontCache{
		fonts:  make(map[string]*truetype.Font),
		folder: folder,
		namer:  FontFileName,
	}
}

func NewFolderFontCache ( folder string ) * FolderFontCache { return & FolderFontCache { fonts : make ( map [ string ] * truetype . Font ) , folder : folder , namer : FontFileName , } }

// NewFolderFontCache creates FolderFontCache


func NewSyncFolderFontCache(folder string) *SyncFolderFontCache {
	return &SyncFolderFontCache{
		fonts:  make(map[string]*truetype.Font),
		folder: folder,
		namer:  FontFileName,
	}
}

func NewSyncFolderFontCache ( folder string ) * SyncFolderFontCache { return & SyncFolderFontCache { fonts : make ( map [ string ] * truetype . Font ) , folder : folder , namer : FontFileName , } }

// NewSyncFolderFontCache creates SyncFolderFontCache


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	gc.SetStrokeColor(image.Black)
	gc.SetFillColor(image.White)
	gc.Save()
	// Draw a (partial) gopher
	gc.Translate(-60, 65)
	gc.Rotate(-30 * (math.Pi / 180.0))
	Draw(gc, 48, 48, 240, 72)
	gc.Restore()

	// Return the output filename
	return samples.Output("gopher2", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
gc
.
SetStrokeColor
(
image
.
Black
)
gc
.
SetFillColor
(
image
.
White
)
gc
.
Save
(
)
// Draw a (partial) gopher
gc
.
Translate
(
60
,
65
)
gc
.
Rotate
(
30
*
(
math
.
Pi
/
180.0
)
)
Draw
(
gc
,
48
,
48
,
240
,
72
)
gc
.
Restore
(
)
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}

// Main draws a rotated face of the gopher. Afterwards it returns
// the filename. This should only be used during testing.

Main draws a rotated face of the gopher . Afterwards it returns the filename . This should only be used during testing .


func NewPdf(orientationStr, unitStr, sizeStr string) *gofpdf.Fpdf {
	pdf := gofpdf.New(orientationStr, unitStr, sizeStr, draw2d.GetFontFolder())
	// to be compatible with draw2d
	pdf.SetMargins(0, 0, 0)
	pdf.SetDrawColor(0, 0, 0)
	pdf.SetFillColor(255, 255, 255)
	pdf.SetLineCapStyle("round")
	pdf.SetLineJoinStyle("round")
	pdf.SetLineWidth(1)
	pdf.AddPage()
	return pdf
}

func
NewPdf
(
orientationStr
,
unitStr
,
sizeStr
string
)
*
gofpdf
.
Fpdf
{
pdf
:=
gofpdf
.
New
(
orientationStr
,
unitStr
,
sizeStr
,
draw2d
.
GetFontFolder
(
)
)
// to be compatible with draw2d
pdf
.
SetMargins
(
0
,
0
,
0
)
pdf
.
SetDrawColor
(
0
,
0
,
0
)
pdf
.
SetFillColor
(
255
,
255
,
255
)
pdf
.
SetLineCapStyle
(
"
"
)
pdf
.
SetLineJoinStyle
(
"
"
)
pdf
.
SetLineWidth
(
1
)
pdf
.
AddPage
(
)
return
pdf
}

// NewPdf creates a new pdf document with the draw2d fontfolder, adds
// a page and set fill color to white.

NewPdf creates a new pdf document with the draw2d fontfolder adds a page and set fill color to white .


func clearRect(gc *GraphicContext, x1, y1, x2, y2 float64) {
	// save state
	f := gc.Current.FillColor
	x, y := gc.pdf.GetXY()
	// cover page with white rectangle
	gc.SetFillColor(white)
	draw2dkit.Rectangle(gc, x1, y1, x2, y2)
	gc.Fill()
	// restore state
	gc.SetFillColor(f)
	gc.pdf.MoveTo(x, y)
}

func
clearRect
(
gc
*
GraphicContext
,
x1
,
y1
,
x2
,
y2
float64
)
{
// save state
f
:=
gc
.
Current
.
FillColor
x
,
y
:=
gc
.
pdf
.
GetXY
(
)
// cover page with white rectangle
gc
.
SetFillColor
(
white
)
draw2dkit
.
Rectangle
(
gc
,
x1
,
y1
,
x2
,
y2
)
gc
.
Fill
(
)
// restore state
gc
.
SetFillColor
(
f
)
gc
.
pdf
.
MoveTo
(
x
,
y
)
}


func NewGraphicContext(pdf *gofpdf.Fpdf) *GraphicContext {
	gc := &GraphicContext{draw2dbase.NewStackGraphicContext(), pdf, DPI}
	gc.SetDPI(DPI)
	return gc
}

func NewGraphicContext ( pdf * gofpdf . Fpdf ) * GraphicContext { gc := & GraphicContext { draw2dbase . NewStackGraphicContext ( ) , pdf , DPI } gc . SetDPI ( DPI ) return gc }

// NewGraphicContext creates a new pdf GraphicContext


func (gc *GraphicContext) Clear() {
	width, height := gc.pdf.GetPageSize()
	clearRect(gc, 0, 0, width, height)
}

func ( gc * GraphicContext ) Clear ( ) { width , height := gc . pdf . GetPageSize ( ) clearRect ( gc , 0 , 0 , width , height ) }

// Clear draws a white rectangle over the whole page


func (gc *GraphicContext) GetStringBounds(s string) (left, top, right, bottom float64) {
	_, h := gc.pdf.GetFontSize()
	d := gc.pdf.GetFontDesc("", "")
	if d.Ascent == 0 {
		// not defined (standard font?), use average of 81%
		top = 0.81 * h
	} else {
		top = -float64(d.Ascent) * h / float64(d.Ascent-d.Descent)
	}
	return 0, top, gc.pdf.GetStringWidth(s), top + h
}

// GetStringBounds returns the approximate pixel bounds of the string s at x, y.
// The left edge of the em square of the first character of s
// and the baseline intersect at 0, 0 in the returned coordinates.
// Therefore the top and left coordinates may well be negative.

GetStringBounds returns the approximate pixel bounds of the string s at x y . The left edge of the em square of the first character of s and the baseline intersect at 0 0 in the returned coordinates . Therefore the top and left coordinates may well be negative .


func (gc *GraphicContext) CreateStringPath(text string, x, y float64) (cursor float64) {
	//fpdf uses the top left corner
	left, top, right, bottom := gc.GetStringBounds(text)
	w := right - left
	h := bottom - top
	// gc.pdf.SetXY(x, y-h) do not use this as y-h might be negative
	margin := gc.pdf.GetCellMargin()
	gc.pdf.MoveTo(x-left-margin, y+top)
	gc.pdf.CellFormat(w, h, text, "", 0, "BL", false, 0, "")
	return w
}

// CreateStringPath creates a path from the string s at x, y, and returns the string width.

CreateStringPath creates a path from the string s at x y and returns the string width .


func (gc *GraphicContext) FillStringAt(text string, x, y float64) (cursor float64) {
	return gc.CreateStringPath(text, x, y)
}

func ( gc * GraphicContext ) FillStringAt ( text string , x , y float64 ) ( cursor float64 ) { return gc . CreateStringPath ( text , x , y ) }


func (gc *GraphicContext) SetStrokeColor(c color.Color) {
	gc.StackGraphicContext.SetStrokeColor(c)
	gc.pdf.SetDrawColor(rgb(c))
}

func ( gc * GraphicContext ) SetStrokeColor ( c color . Color ) { gc . StackGraphicContext . SetStrokeColor ( c ) gc . pdf . SetDrawColor ( rgb ( c ) ) }

// overwrite StackGraphicContext methods
// SetStrokeColor sets the stroke color

overwrite StackGraphicContext methods SetStrokeColor sets the stroke color


func (gc *GraphicContext) SetFillColor(c color.Color) {
	gc.StackGraphicContext.SetFillColor(c)
	gc.pdf.SetFillColor(rgb(c))
	gc.pdf.SetTextColor(rgb(c))
}

func ( gc * GraphicContext ) SetFillColor ( c color . Color ) { gc . StackGraphicContext . SetFillColor ( c ) gc . pdf . SetFillColor ( rgb ( c ) ) gc . pdf . SetTextColor ( rgb ( c ) ) }

// SetFillColor sets the fill and text color


func (gc *GraphicContext) SetLineDash(Dash []float64, DashOffset float64) {
	gc.StackGraphicContext.SetLineDash(Dash, DashOffset)
	gc.pdf.SetDashPattern(Dash, DashOffset)
}

func ( gc * GraphicContext ) SetLineDash ( Dash [ ] float64 , DashOffset float64 ) { gc . StackGraphicContext . SetLineDash ( Dash , DashOffset ) gc . pdf . SetDashPattern ( Dash , DashOffset ) }

// SetLineDash sets the line dash pattern


func (gc *GraphicContext) SetLineWidth(LineWidth float64) {
	gc.StackGraphicContext.SetLineWidth(LineWidth)
	gc.pdf.SetLineWidth(LineWidth)
}

func ( gc * GraphicContext ) SetLineWidth ( LineWidth float64 ) { gc . StackGraphicContext . SetLineWidth ( LineWidth ) gc . pdf . SetLineWidth ( LineWidth ) }


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	// Draw hello world
	Draw(gc, fmt.Sprintf("Hello World %d dpi", gc.GetDPI()))

	// Return the output filename
	return samples.Output("helloworld", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
// Draw hello world
Draw
(
gc
,
fmt
.
Sprintf
(
"
"
,
gc
.
GetDPI
(
)
)
)
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}

// Main draws "Hello World" and returns the filename. This should only be
// used during testing.

Main draws Hello World and returns the filename . This should only be used during testing .


func Draw(gc draw2d.GraphicContext, text string) {
	// Draw a rounded rectangle using default colors
	draw2dkit.RoundedRectangle(gc, 5, 5, 135, 95, 10, 10)
	gc.FillStroke()

	// Set the font luximbi.ttf
	gc.SetFontData(draw2d.FontData{Name: "luxi", Family: draw2d.FontFamilyMono, Style: draw2d.FontStyleBold | draw2d.FontStyleItalic})
	// Set the fill text color to black
	gc.SetFillColor(image.Black)
	gc.SetFontSize(14)
	// Display Hello World
	gc.FillStringAt("Hello World", 8, 52)
}


func SaveToPngFile(filePath string, m image.Image) error {
	// Create the file
	f, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer f.Close()
	// Create Writer from file
	b := bufio.NewWriter(f)
	// Write the image into the buffer
	err = png.Encode(b, m)
	if err != nil {
		return err
	}
	err = b.Flush()
	if err != nil {
		return err
	}
	return nil
}

func
SaveToPngFile
(
filePath
string
,
m
image
.
Image
)
error
{
// Create the file
f
,
err
:=
os
.
Create
(
filePath
)
if
err
!=
{
return
err
}
defer
f
.
Close
(
)
// Create Writer from file
b
:=
bufio
.
NewWriter
(
f
)
// Write the image into the buffer
err
=
png
.
Encode
(
b
,
m
)
if
err
!=
{
return
err
}
err
=
b
.
Flush
(
)
if
err
!=
{
return
err
}
return
}

// SaveToPngFile create and save an image to a file using PNG format


func LoadFromPngFile(filePath string) (image.Image, error) {
	// Open file
	f, err := os.OpenFile(filePath, 0, 0)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	b := bufio.NewReader(f)
	img, err := png.Decode(b)
	if err != nil {
		return nil, err
	}
	return img, nil
}

func
LoadFromPngFile
(
filePath
string
)
(
image
.
Image
,
error
)
{
// Open file
f
,
err
:=
os
.
OpenFile
(
filePath
,
0
,
0
)
if
err
!=
{
return
,
err
}
defer
f
.
Close
(
)
b
:=
bufio
.
NewReader
(
f
)
img
,
err
:=
png
.
Decode
(
b
)
if
err
!=
{
return
,
err
}
return
img
,
}


func Resource(folder, filename, ext string) string {
	var root string
	if ext == "pdf" || ext == "svg" {
		root = "../"
	}
	return fmt.Sprintf("%sresource/%s/%s", root, folder, filename)
}

func Resource ( folder , filename , ext string ) string { var root string if ext == " " || ext == " " { root = " " } return fmt . Sprintf ( " " , root , folder , filename ) }

// Resource returns a resource filename for testing.

Resource returns a resource filename for testing .


func Output(name, ext string) string {
	var root string
	if ext == "pdf" || ext == "svg" {
		root = "../"
	}
	return fmt.Sprintf("%soutput/samples/%s.%s", root, name, ext)
}

func Output ( name , ext string ) string { var root string if ext == " " || ext == " " { root = " " } return fmt . Sprintf ( " " , root , name , ext ) }

// Output returns the output filename for testing.

Output returns the output filename for testing .


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	gc.Save()

	// flip the image
	gc.Translate(0, 200)
	gc.Scale(0.35, -0.35)
	gc.Translate(70, -200)

	// Tiger postscript drawing
	tiger := samples.Resource("image", "tiger.ps", ext)

	// Draw tiger
	Draw(gc, tiger)
	gc.Restore()

	// Return the output filename
	return samples.Output("postscript", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
gc
.
Save
(
)
// flip the image
gc
.
Translate
(
0
,
200
)
gc
.
Scale
(
0.35
,
0.35
)
gc
.
Translate
(
70
,
200
)
// Tiger postscript drawing
tiger
:=
samples
.
Resource
(
"
"
,
"
"
,
ext
)
// Draw tiger
Draw
(
gc
,
tiger
)
gc
.
Restore
(
)
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}


func Draw(gc draw2d.GraphicContext, filename string) {
	// Open the postscript
	src, err := os.OpenFile(filename, 0, 0)
	if err != nil {
		panic(err)
	}
	defer src.Close()
	bytes, err := ioutil.ReadAll(src)
	reader := strings.NewReader(string(bytes))

	// Initialize and interpret the postscript
	interpreter := ps.NewInterpreter(gc)
	interpreter.Execute(reader)
}


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	// Draw the droid
	Draw(gc, 297, 210)

	// Return the output filename
	return samples.Output("geometry", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
// Draw the droid
Draw
(
gc
,
297
,
210
)
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}

// Main draws geometry and returns the filename. This should only be
// used during testing.

Main draws geometry and returns the filename . This should only be used during testing .


func Bubble(gc draw2d.GraphicContext, x, y, width, height float64) {
	sx, sy := width/100, height/100
	gc.MoveTo(x+sx*50, y)
	gc.QuadCurveTo(x, y, x, y+sy*37.5)
	gc.QuadCurveTo(x, y+sy*75, x+sx*25, y+sy*75)
	gc.QuadCurveTo(x+sx*25, y+sy*95, x+sx*5, y+sy*100)
	gc.QuadCurveTo(x+sx*35, y+sy*95, x+sx*40, y+sy*75)
	gc.QuadCurveTo(x+sx*100, y+sy*75, x+sx*100, y+sy*37.5)
	gc.QuadCurveTo(x+sx*100, y, x+sx*50, y)
	gc.Stroke()
}

func Bubble ( gc draw2d . GraphicContext , x , y , width , height float64 ) { sx , sy := width / 100 , height / 100 gc . MoveTo ( x + sx * 50 , y ) gc . QuadCurveTo ( x , y , x , y + sy * 37.5 ) gc . QuadCurveTo ( x , y + sy * 75 , x + sx * 25 , y + sy * 75 ) gc . QuadCurveTo ( x + sx * 25 , y + sy * 95 , x + sx * 5 , y + sy * 100 ) gc . QuadCurveTo ( x + sx * 35 , y + sy * 95 , x + sx * 40 , y + sy * 75 ) gc . QuadCurveTo ( x + sx * 100 , y + sy * 75 , x + sx * 100 , y + sy * 37.5 ) gc . QuadCurveTo ( x + sx * 100 , y , x + sx * 50 , y ) gc . Stroke ( ) }


func Dash(gc draw2d.GraphicContext, x, y, width, height float64) {
	sx, sy := width/162, height/205
	gc.SetStrokeColor(image.Black)
	gc.SetLineDash([]float64{height / 10, height / 50, height / 50, height / 50}, -50.0)
	gc.SetLineCap(draw2d.ButtCap)
	gc.SetLineJoin(draw2d.RoundJoin)
	gc.SetLineWidth(height / 50)

	gc.MoveTo(x+sx*60.0, y)
	gc.LineTo(x+sx*60.0, y)
	gc.LineTo(x+sx*162, y+sy*205)
	rLineTo(gc, sx*-102.4, 0)
	gc.CubicCurveTo(x+sx*-17, y+sy*205, x+sx*-17, y+sy*103, x+sx*60.0, y+sy*103.0)
	gc.Stroke()
	gc.SetLineDash(nil, 0.0)
}

func Dash ( gc draw2d . GraphicContext , x , y , width , height float64 ) { sx , sy := width / 162 , height / 205 gc . SetStrokeColor ( image . Black ) gc . SetLineDash ( [ ] float64 { height / 10 , height / 50 , height / 50 , height / 50 } , - 50.0 ) gc . SetLineCap ( draw2d . ButtCap ) gc . SetLineJoin ( draw2d . RoundJoin ) gc . SetLineWidth ( height / 50 ) gc . MoveTo ( x + sx * 60.0 , y ) gc . LineTo ( x + sx * 60.0 , y ) gc . LineTo ( x + sx * 162 , y + sy * 205 ) rLineTo ( gc , sx * - 102.4 , 0 ) gc . CubicCurveTo ( x + sx * - 17 , y + sy * 205 , x + sx * - 17 , y + sy * 103 , x + sx * 60.0 , y + sy * 103.0 ) gc . Stroke ( ) gc . SetLineDash ( nil , 0.0 ) }

// Dash draws a line with a dash pattern


func CubicCurve(gc draw2d.GraphicContext, x, y, width, height float64) {
	sx, sy := width/162, height/205
	x0, y0 := x, y+sy*100.0
	x1, y1 := x+sx*75, y+sy*205
	x2, y2 := x+sx*125, y
	x3, y3 := x+sx*205, y+sy*100

	gc.SetStrokeColor(image.Black)
	gc.SetFillColor(color.NRGBA{0xAA, 0xAA, 0xAA, 0xFF})
	gc.SetLineWidth(width / 10)
	gc.MoveTo(x0, y0)
	gc.CubicCurveTo(x1, y1, x2, y2, x3, y3)
	gc.Stroke()

	gc.SetStrokeColor(color.NRGBA{0xFF, 0x33, 0x33, 0x88})

	gc.SetLineWidth(width / 20)
	// draw segment of curve
	gc.MoveTo(x0, y0)
	gc.LineTo(x1, y1)
	gc.LineTo(x2, y2)
	gc.LineTo(x3, y3)
	gc.Stroke()
}

func
CubicCurve
(
gc
draw2d
.
GraphicContext
,
x
,
y
,
width
,
height
float64
)
{
sx
,
sy
:=
width
/
162
,
height
/
205
x0
,
y0
:=
x
,
y
+
sy
*
100.0
x1
,
y1
:=
x
+
sx
*
75
,
y
+
sy
*
205
x2
,
y2
:=
x
+
sx
*
125
,
y
x3
,
y3
:=
x
+
sx
*
205
,
y
+
sy
*
100
gc
.
SetStrokeColor
(
image
.
Black
)
gc
.
SetFillColor
(
color
.
NRGBA
{
0xAA
,
0xAA
,
0xAA
,
0xFF
}
)
gc
.
SetLineWidth
(
width
/
10
)
gc
.
MoveTo
(
x0
,
y0
)
gc
.
CubicCurveTo
(
x1
,
y1
,
x2
,
y2
,
x3
,
y3
)
gc
.
Stroke
(
)
gc
.
SetStrokeColor
(
color
.
NRGBA
{
0xFF
,
0x33
,
0x33
,
0x88
}
)
gc
.
SetLineWidth
(
width
/
20
)
// draw segment of curve
gc
.
MoveTo
(
x0
,
y0
)
gc
.
LineTo
(
x1
,
y1
)
gc
.
LineTo
(
x2
,
y2
)
gc
.
LineTo
(
x3
,
y3
)
gc
.
Stroke
(
)
}

// CubicCurve draws a cubic curve with its control points.

CubicCurve draws a cubic curve with its control points .


func FillStroke(gc draw2d.GraphicContext, x, y, width, height float64) {
	sx, sy := width/210, height/215
	gc.MoveTo(x+sx*113.0, y)
	gc.LineTo(x+sx*215.0, y+sy*215)
	rLineTo(gc, sx*-100, 0)
	gc.CubicCurveTo(x+sx*35, y+sy*215, x+sx*35, y+sy*113, x+sx*113.0, y+sy*113)
	gc.Close()

	gc.MoveTo(x+sx*50.0, y)
	rLineTo(gc, sx*51.2, sy*51.2)
	rLineTo(gc, sx*-51.2, sy*51.2)
	rLineTo(gc, sx*-51.2, sy*-51.2)
	gc.Close()

	gc.SetLineWidth(width / 20.0)
	gc.SetFillColor(color.NRGBA{0, 0, 0xFF, 0xFF})
	gc.SetStrokeColor(image.Black)
	gc.FillStroke()
}

func FillStroke ( gc draw2d . GraphicContext , x , y , width , height float64 ) { sx , sy := width / 210 , height / 215 gc . MoveTo ( x + sx * 113.0 , y ) gc . LineTo ( x + sx * 215.0 , y + sy * 215 ) rLineTo ( gc , sx * - 100 , 0 ) gc . CubicCurveTo ( x + sx * 35 , y + sy * 215 , x + sx * 35 , y + sy * 113 , x + sx * 113.0 , y + sy * 113 ) gc . Close ( ) gc . MoveTo ( x + sx * 50.0 , y ) rLineTo ( gc , sx * 51.2 , sy * 51.2 ) rLineTo ( gc , sx * - 51.2 , sy * 51.2 ) rLineTo ( gc , sx * - 51.2 , sy * - 51.2 ) gc . Close ( ) gc . SetLineWidth ( width / 20.0 ) gc . SetFillColor ( color . NRGBA { 0 , 0 , 0xFF , 0xFF } ) gc . SetStrokeColor ( image . Black ) gc . FillStroke ( ) }

// FillStroke first fills and afterwards strokes a path.

FillStroke first fills and afterwards strokes a path .


func FillStyle(gc draw2d.GraphicContext, x, y, width, height float64) {
	sx, sy := width/232, height/220
	gc.SetLineWidth(width / 40)

	draw2dkit.Rectangle(gc, x+sx*0, y+sy*12, x+sx*232, y+sy*70)

	var wheel1, wheel2 draw2d.Path
	wheel1.ArcTo(x+sx*52, y+sy*70, sx*40, sy*40, 0, 2*math.Pi)
	wheel2.ArcTo(x+sx*180, y+sy*70, sx*40, sy*40, 0, -2*math.Pi)

	gc.SetFillRule(draw2d.FillRuleEvenOdd)
	gc.SetFillColor(color.NRGBA{0, 0xB2, 0, 0xFF})

	gc.SetStrokeColor(image.Black)
	gc.FillStroke(&wheel1, &wheel2)

	draw2dkit.Rectangle(gc, x, y+sy*140, x+sx*232, y+sy*198)
	wheel1.Clear()
	wheel1.ArcTo(x+sx*52, y+sy*198, sx*40, sy*40, 0, 2*math.Pi)
	wheel2.Clear()
	wheel2.ArcTo(x+sx*180, y+sy*198, sx*40, sy*40, 0, -2*math.Pi)

	gc.SetFillRule(draw2d.FillRuleWinding)
	gc.SetFillColor(color.NRGBA{0, 0, 0xE5, 0xFF})
	gc.FillStroke(&wheel1, &wheel2)
}

func FillStyle ( gc draw2d . GraphicContext , x , y , width , height float64 ) { sx , sy := width / 232 , height / 220 gc . SetLineWidth ( width / 40 ) draw2dkit . Rectangle ( gc , x + sx * 0 , y + sy * 12 , x + sx * 232 , y + sy * 70 ) var wheel1 , wheel2 draw2d . Path wheel1 . ArcTo ( x + sx * 52 , y + sy * 70 , sx * 40 , sy * 40 , 0 , 2 * math . Pi ) wheel2 . ArcTo ( x + sx * 180 , y + sy * 70 , sx * 40 , sy * 40 , 0 , - 2 * math . Pi ) gc . SetFillRule ( draw2d . FillRuleEvenOdd ) gc . SetFillColor ( color . NRGBA { 0 , 0xB2 , 0 , 0xFF } ) gc . SetStrokeColor ( image . Black ) gc . FillStroke ( & wheel1 , & wheel2 ) draw2dkit . Rectangle ( gc , x , y + sy * 140 , x + sx * 232 , y + sy * 198 ) wheel1 . Clear ( ) wheel1 . ArcTo ( x + sx * 52 , y + sy * 198 , sx * 40 , sy * 40 , 0 , 2 * math . Pi ) wheel2 . Clear ( ) wheel2 . ArcTo ( x + sx * 180 , y + sy * 198 , sx * 40 , sy * 40 , 0 , - 2 * math . Pi ) gc . SetFillRule ( draw2d . FillRuleWinding ) gc . SetFillColor ( color . NRGBA { 0 , 0 , 0xE5 , 0xFF } ) gc . FillStroke ( & wheel1 , & wheel2 ) }

// FillStyle demonstrates the difference between even odd and non zero winding rule.

FillStyle demonstrates the difference between even odd and non zero winding rule .


func PathTransform(gc draw2d.GraphicContext, x, y, width, height float64) {
	gc.Save()
	gc.SetLineWidth(width / 10)
	gc.Translate(x+width/2, y+height/2)
	gc.Scale(1, 4)
	gc.ArcTo(0, 0, width/8, height/8, 0, math.Pi*2)
	gc.Close()
	gc.Stroke()
	gc.Restore()
}

func PathTransform ( gc draw2d . GraphicContext , x , y , width , height float64 ) { gc . Save ( ) gc . SetLineWidth ( width / 10 ) gc . Translate ( x + width / 2 , y + height / 2 ) gc . Scale ( 1 , 4 ) gc . ArcTo ( 0 , 0 , width / 8 , height / 8 , 0 , math . Pi * 2 ) gc . Close ( ) gc . Stroke ( ) gc . Restore ( ) }

// PathTransform scales a path differently in horizontal and vertical direction.

PathTransform scales a path differently in horizontal and vertical direction .


func Star(gc draw2d.GraphicContext, x, y, width, height float64) {
	gc.Save()
	gc.Translate(x+width/2, y+height/2)
	gc.SetLineWidth(width / 40)
	for i := 0.0; i < 360; i = i + 10 { // Go from 0 to 360 degrees in 10 degree steps
		gc.Save()                        // Keep rotations temporary
		gc.Rotate(i * (math.Pi / 180.0)) // Rotate by degrees on stack from 'for'
		gc.MoveTo(0, 0)
		gc.LineTo(width/2, 0)
		gc.Stroke()
		gc.Restore()
	}
	gc.Restore()
}


func Draw(gc draw2d.GraphicContext, width, height float64) {
	mx, my := width*0.025, height*0.025 // margin
	dx, dy := (width-2*mx)/4, (height-2*my)/3
	w, h := dx-2*mx, dy-2*my
	x0, y := 2*mx, 2*my
	x := x0
	Bubble(gc, x, y, w, h)
	x += dx
	CurveRectangle(gc, x, y, w, h, color.NRGBA{0x80, 0, 0, 0x80}, color.NRGBA{0x80, 0x80, 0xFF, 0xFF})
	x += dx
	Dash(gc, x, y, w, h)
	x += dx
	Arc(gc, x, y, w, h)
	x = x0
	y += dy
	ArcNegative(gc, x, y, w, h)
	x += dx
	CubicCurve(gc, x, y, w, h)
	x += dx
	FillString(gc, x, y, w, h)
	x += dx
	FillStroke(gc, x, y, w, h)
	x = x0
	y += dy
	FillStyle(gc, x, y, w, h)
	x += dx
	PathTransform(gc, x, y, w, h)
	x += dx
	Star(gc, x, y, w, h)
	x += dx
	gopher2.Draw(gc, x, y, w, h/2)
}

func
Draw
(
gc
draw2d
.
GraphicContext
,
width
,
height
float64
)
{
mx
,
my
:=
width
*
0.025
,
height
*
0.025
// margin
dx
,
dy
:=
(
width
2
*
mx
)
/
4
,
(
height
2
*
my
)
/
3
w
,
h
:=
dx
2
*
mx
,
dy
2
*
my
x0
,
y
:=
2
*
mx
,
2
*
my
x
:=
x0
Bubble
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
CurveRectangle
(
gc
,
x
,
y
,
w
,
h
,
color
.
NRGBA
{
0x80
,
0
,
0
,
0x80
}
,
color
.
NRGBA
{
0x80
,
0x80
,
0xFF
,
0xFF
}
)
x
+=
dx
Dash
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
Arc
(
gc
,
x
,
y
,
w
,
h
)
x
=
x0
y
+=
dy
ArcNegative
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
CubicCurve
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
FillString
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
FillStroke
(
gc
,
x
,
y
,
w
,
h
)
x
=
x0
y
+=
dy
FillStyle
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
PathTransform
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
Star
(
gc
,
x
,
y
,
w
,
h
)
x
+=
dx
gopher2
.
Draw
(
gc
,
x
,
y
,
w
,
h
/
2
)
}


func ConvertPath(path *draw2d.Path, pdf Vectorizer) {
	var startX, startY float64 = 0, 0
	i := 0
	for _, cmp := range path.Components {
		switch cmp {
		case draw2d.MoveToCmp:
			startX, startY = path.Points[i], path.Points[i+1]
			pdf.MoveTo(startX, startY)
			i += 2
		case draw2d.LineToCmp:
			pdf.LineTo(path.Points[i], path.Points[i+1])
			i += 2
		case draw2d.QuadCurveToCmp:
			pdf.CurveTo(path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3])
			i += 4
		case draw2d.CubicCurveToCmp:
			pdf.CurveBezierCubicTo(path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3], path.Points[i+4], path.Points[i+5])
			i += 6
		case draw2d.ArcToCmp:
			pdf.ArcTo(path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3],
				0, // degRotate
				path.Points[i+4]*deg,                    // degStart = startAngle
				(path.Points[i+4]-path.Points[i+5])*deg) // degEnd = startAngle-angle
			i += 6
		case draw2d.CloseCmp:
			pdf.LineTo(startX, startY)
			pdf.ClosePath()
		}
	}
}

func
ConvertPath
(
path
*
draw2d
.
Path
,
pdf
Vectorizer
)
{
var
startX
,
startY
float64
=
0
,
0
i
:=
0
for
_
,
cmp
:=
range
path
.
Components
{
switch
cmp
{
case
draw2d
.
MoveToCmp
:
startX
,
startY
=
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
pdf
.
MoveTo
(
startX
,
startY
)
i
+=
2
case
draw2d
.
LineToCmp
:
pdf
.
LineTo
(
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
)
i
+=
2
case
draw2d
.
QuadCurveToCmp
:
pdf
.
CurveTo
(
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
,
path
.
Points
[
i
+
2
]
,
path
.
Points
[
i
+
3
]
)
i
+=
4
case
draw2d
.
CubicCurveToCmp
:
pdf
.
CurveBezierCubicTo
(
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
,
path
.
Points
[
i
+
2
]
,
path
.
Points
[
i
+
3
]
,
path
.
Points
[
i
+
4
]
,
path
.
Points
[
i
+
5
]
)
i
+=
6
case
draw2d
.
ArcToCmp
:
pdf
.
ArcTo
(
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
,
path
.
Points
[
i
+
2
]
,
path
.
Points
[
i
+
3
]
,
0
,
// degRotate
path
.
Points
[
i
+
4
]
*
deg
,
// degStart = startAngle
(
path
.
Points
[
i
+
4
]
path
.
Points
[
i
+
5
]
)
*
deg
)
// degEnd = startAngle-angle
i
+=
6
case
draw2d
.
CloseCmp
:
pdf
.
LineTo
(
startX
,
startY
)
pdf
.
ClosePath
(
)
}
}
}

// ConvertPath converts a paths to the pdf api


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	// Draw the line
	const offset = 75.0
	x := 35.0
	caps := []draw2d.LineCap{draw2d.ButtCap, draw2d.SquareCap, draw2d.RoundCap}
	joins := []draw2d.LineJoin{draw2d.BevelJoin, draw2d.MiterJoin, draw2d.RoundJoin}
	for i := range caps {
		Draw(gc, caps[i], joins[i], x, 50, x, 160, offset)
		x += offset
	}

	// Return the output filename
	return samples.Output("linecapjoin", ext), nil
}

func
Main
(
gc
draw2d
.
GraphicContext
,
ext
string
)
(
string
,
error
)
{
// Draw the line
const
offset
=
75.0
x
:=
35.0
caps
:=
[
]
draw2d
.
LineCap
{
draw2d
.
ButtCap
,
draw2d
.
SquareCap
,
draw2d
.
RoundCap
}
joins
:=
[
]
draw2d
.
LineJoin
{
draw2d
.
BevelJoin
,
draw2d
.
MiterJoin
,
draw2d
.
RoundJoin
}
for
i
:=
range
caps
{
Draw
(
gc
,
caps
[
i
]
,
joins
[
i
]
,
x
,
50
,
x
,
160
,
offset
)
x
+=
offset
}
// Return the output filename
return
samples
.
Output
(
"
"
,
ext
)
,
}

// Main draws the different line caps and joins.
// This should only be used during testing.

Main draws the different line caps and joins . This should only be used during testing .


func Draw(gc draw2d.GraphicContext, cap draw2d.LineCap, join draw2d.LineJoin,
	x0, y0, x1, y1, offset float64) {
	gc.SetLineCap(cap)
	gc.SetLineJoin(join)

	// Draw thick line
	gc.SetStrokeColor(color.NRGBA{0x33, 0x33, 0x33, 0xFF})
	gc.SetLineWidth(30.0)
	gc.MoveTo(x0, y0)
	gc.LineTo((x0+x1)/2+offset, (y0+y1)/2)
	gc.LineTo(x1, y1)
	gc.Stroke()

	// Draw thin helping line
	gc.SetStrokeColor(color.NRGBA{0xFF, 0x33, 0x33, 0xFF})
	gc.SetLineWidth(2.56)
	gc.MoveTo(x0, y0)
	gc.LineTo((x0+x1)/2+offset, (y0+y1)/2)
	gc.LineTo(x1, y1)
	gc.Stroke()
}

func
Draw
(
gc
draw2d
.
GraphicContext
,
cap
draw2d
.
LineCap
,
join
draw2d
.
LineJoin
,
x0
,
y0
,
x1
,
y1
,
offset
float64
)
{
gc
.
SetLineCap
(
cap
)
gc
.
SetLineJoin
(
join
)
// Draw thick line
gc
.
SetStrokeColor
(
color
.
NRGBA
{
0x33
,
0x33
,
0x33
,
0xFF
}
)
gc
.
SetLineWidth
(
30.0
)
gc
.
MoveTo
(
x0
,
y0
)
gc
.
LineTo
(
(
x0
+
x1
)
/
2
+
offset
,
(
y0
+
y1
)
/
2
)
gc
.
LineTo
(
x1
,
y1
)
gc
.
Stroke
(
)
// Draw thin helping line
gc
.
SetStrokeColor
(
color
.
NRGBA
{
0xFF
,
0x33
,
0x33
,
0xFF
}
)
gc
.
SetLineWidth
(
2.56
)
gc
.
MoveTo
(
x0
,
y0
)
gc
.
LineTo
(
(
x0
+
x1
)
/
2
+
offset
,
(
y0
+
y1
)
/
2
)
gc
.
LineTo
(
x1
,
y1
)
gc
.
Stroke
(
)
}

// Draw a line with an angle with specified line cap and join


func DrawContour(path draw2d.PathBuilder, ps []truetype.Point, dx, dy float64) {
	if len(ps) == 0 {
		return
	}
	startX, startY := pointToF64Point(ps[0])
	path.MoveTo(startX+dx, startY+dy)
	q0X, q0Y, on0 := startX, startY, true
	for _, p := range ps[1:] {
		qX, qY := pointToF64Point(p)
		on := p.Flags&0x01 != 0
		if on {
			if on0 {
				path.LineTo(qX+dx, qY+dy)
			} else {
				path.QuadCurveTo(q0X+dx, q0Y+dy, qX+dx, qY+dy)
			}
		} else {
			if on0 {
				// No-op.
			} else {
				midX := (q0X + qX) / 2
				midY := (q0Y + qY) / 2
				path.QuadCurveTo(q0X+dx, q0Y+dy, midX+dx, midY+dy)
			}
		}
		q0X, q0Y, on0 = qX, qY, on
	}
	// Close the curve.
	if on0 {
		path.LineTo(startX+dx, startY+dy)
	} else {
		path.QuadCurveTo(q0X+dx, q0Y+dy, startX+dx, startY+dy)
	}
}

func
DrawContour
(
path
draw2d
.
PathBuilder
,
ps
[
]
truetype
.
Point
,
dx
,
dy
float64
)
{
if
len
(
ps
)
==
0
{
return
}
startX
,
startY
:=
pointToF64Point
(
ps
[
0
]
)
path
.
MoveTo
(
startX
+
dx
,
startY
+
dy
)
q0X
,
q0Y
,
on0
:=
startX
,
startY
,
true
for
_
,
p
:=
range
ps
[
1
:
]
{
qX
,
qY
:=
pointToF64Point
(
p
)
on
:=
p
.
Flags
&
0x01
!=
0
if
on
{
if
on0
{
path
.
LineTo
(
qX
+
dx
,
qY
+
dy
)
}
else
{
path
.
QuadCurveTo
(
q0X
+
dx
,
q0Y
+
dy
,
qX
+
dx
,
qY
+
dy
)
}
}
else
{
if
on0
{
// No-op.
}
else
{
midX
:=
(
q0X
+
qX
)
/
2
midY
:=
(
q0Y
+
qY
)
/
2
path
.
QuadCurveTo
(
q0X
+
dx
,
q0Y
+
dy
,
midX
+
dx
,
midY
+
dy
)
}
}
q0X
,
q0Y
,
on0
=
qX
,
qY
,
on
}
// Close the curve.
if
on0
{
path
.
LineTo
(
startX
+
dx
,
startY
+
dy
)
}
else
{
path
.
QuadCurveTo
(
q0X
+
dx
,
q0Y
+
dy
,
startX
+
dx
,
startY
+
dy
)
}
}

// DrawContour draws the given closed contour at the given sub-pixel offset.

DrawContour draws the given closed contour at the given sub - pixel offset .


func Flatten(path *draw2d.Path, flattener Flattener, scale float64) {
	// First Point
	var startX, startY float64 = 0, 0
	// Current Point
	var x, y float64 = 0, 0
	i := 0
	for _, cmp := range path.Components {
		switch cmp {
		case draw2d.MoveToCmp:
			x, y = path.Points[i], path.Points[i+1]
			startX, startY = x, y
			if i != 0 {
				flattener.End()
			}
			flattener.MoveTo(x, y)
			i += 2
		case draw2d.LineToCmp:
			x, y = path.Points[i], path.Points[i+1]
			flattener.LineTo(x, y)
			flattener.LineJoin()
			i += 2
		case draw2d.QuadCurveToCmp:
			TraceQuad(flattener, path.Points[i-2:], 0.5)
			x, y = path.Points[i+2], path.Points[i+3]
			flattener.LineTo(x, y)
			i += 4
		case draw2d.CubicCurveToCmp:
			TraceCubic(flattener, path.Points[i-2:], 0.5)
			x, y = path.Points[i+4], path.Points[i+5]
			flattener.LineTo(x, y)
			i += 6
		case draw2d.ArcToCmp:
			x, y = TraceArc(flattener, path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3], path.Points[i+4], path.Points[i+5], scale)
			flattener.LineTo(x, y)
			i += 6
		case draw2d.CloseCmp:
			flattener.LineTo(startX, startY)
			flattener.Close()
		}
	}
	flattener.End()
}

func
Flatten
(
path
*
draw2d
.
Path
,
flattener
Flattener
,
scale
float64
)
{
// First Point
var
startX
,
startY
float64
=
0
,
0
// Current Point
var
x
,
y
float64
=
0
,
0
i
:=
0
for
_
,
cmp
:=
range
path
.
Components
{
switch
cmp
{
case
draw2d
.
MoveToCmp
:
x
,
y
=
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
startX
,
startY
=
x
,
y
if
i
!=
0
{
flattener
.
End
(
)
}
flattener
.
MoveTo
(
x
,
y
)
i
+=
2
case
draw2d
.
LineToCmp
:
x
,
y
=
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
flattener
.
LineTo
(
x
,
y
)
flattener
.
LineJoin
(
)
i
+=
2
case
draw2d
.
QuadCurveToCmp
:
TraceQuad
(
flattener
,
path
.
Points
[
i
2
:
]
,
0.5
)
x
,
y
=
path
.
Points
[
i
+
2
]
,
path
.
Points
[
i
+
3
]
flattener
.
LineTo
(
x
,
y
)
i
+=
4
case
draw2d
.
CubicCurveToCmp
:
TraceCubic
(
flattener
,
path
.
Points
[
i
2
:
]
,
0.5
)
x
,
y
=
path
.
Points
[
i
+
4
]
,
path
.
Points
[
i
+
5
]
flattener
.
LineTo
(
x
,
y
)
i
+=
6
case
draw2d
.
ArcToCmp
:
x
,
y
=
TraceArc
(
flattener
,
path
.
Points
[
i
]
,
path
.
Points
[
i
+
1
]
,
path
.
Points
[
i
+
2
]
,
path
.
Points
[
i
+
3
]
,
path
.
Points
[
i
+
4
]
,
path
.
Points
[
i
+
5
]
,
scale
)
flattener
.
LineTo
(
x
,
y
)
i
+=
6
case
draw2d
.
CloseCmp
:
flattener
.
LineTo
(
startX
,
startY
)
flattener
.
Close
(
)
}
}
flattener
.
End
(
)
}

// Flatten convert curves into straight segments keeping join segments info


func (gc *GraphicContext) Clear() {
	width, height := gc.img.Bounds().Dx(), gc.img.Bounds().Dy()
	gc.ClearRect(0, 0, width, height)
}

func ( gc * GraphicContext ) Clear ( ) { width , height := gc . img . Bounds ( ) . Dx ( ) , gc . img . Bounds ( ) . Dy ( ) gc . ClearRect ( 0 , 0 , width , height ) }

// Clear fills the current canvas with a default transparent color


func (gc *GraphicContext) ClearRect(x1, y1, x2, y2 int) {
	imageColor := image.NewUniform(gc.Current.FillColor)
	draw.Draw(gc.img, image.Rect(x1, y1, x2, y2), imageColor, image.ZP, draw.Over)
}

func ( gc * GraphicContext ) ClearRect ( x1 , y1 , x2 , y2 int ) { imageColor := image . NewUniform ( gc . Current . FillColor ) draw . Draw ( gc . img , image . Rect ( x1 , y1 , x2 , y2 ) , imageColor , image . ZP , draw . Over ) }

// ClearRect fills the current canvas with a default transparent color at the specified rectangle


func DrawImage(src image.Image, dest draw.Image, tr draw2d.Matrix, op draw.Op, filter ImageFilter) {
	var transformer draw.Transformer
	switch filter {
	case LinearFilter:
		transformer = draw.NearestNeighbor
	case BilinearFilter:
		transformer = draw.BiLinear
	case BicubicFilter:
		transformer = draw.CatmullRom
	}
	transformer.Transform(dest, f64.Aff3{tr[0], tr[1], tr[4], tr[2], tr[3], tr[5]}, src, src.Bounds(), op, nil)
}

func DrawImage ( src image . Image , dest draw . Image , tr draw2d . Matrix , op draw . Op , filter ImageFilter ) { var transformer draw . Transformer switch filter { case LinearFilter : transformer = draw . NearestNeighbor case BilinearFilter : transformer = draw . BiLinear case BicubicFilter : transformer = draw . CatmullRom } transformer . Transform ( dest , f64 . Aff3 { tr [ 0 ] , tr [ 1 ] , tr [ 4 ] , tr [ 2 ] , tr [ 3 ] , tr [ 5 ] } , src , src . Bounds ( ) , op , nil ) }

// DrawImage draws an image into dest using an affine transformation matrix, an op and a filter

DrawImage draws an image into dest using an affine transformation matrix an op and a filter


func Main(gc draw2d.GraphicContext, ext string) (string, error) {
	// Margin between the image and the frame
	const margin = 30
	// Line width od the frame
	const lineWidth = 3

	// Gopher image
	gopher := samples.Resource("image", "gopher.png", ext)

	// Draw gopher
	err := Draw(gc, gopher, 297, 210, margin, lineWidth)

	// Return the output filename
	return samples.Output("frameimage", ext), err
}

// Main draws the image frame and returns the filename.
// This should only be used during testing.

Main draws the image frame and returns the filename . This should only be used during testing .


func Draw(gc draw2d.GraphicContext, png string,
	dw, dh, margin, lineWidth float64) error {
	// Draw frame
	draw2dkit.RoundedRectangle(gc, lineWidth, lineWidth, dw-lineWidth, dh-lineWidth, 100, 100)
	gc.SetLineWidth(lineWidth)
	gc.FillStroke()

	// load the source image
	source, err := draw2dimg.LoadFromPngFile(png)
	if err != nil {
		return err
	}
	// Size of source image
	sw, sh := float64(source.Bounds().Dx()), float64(source.Bounds().Dy())
	// Draw image to fit in the frame
	// TODO Seems to have a transform bug here on draw image
	scale := math.Min((dw-margin*2)/sw, (dh-margin*2)/sh)
	gc.Save()
	gc.Translate((dw-sw*scale)/2, (dh-sh*scale)/2)
	gc.Scale(scale, scale)
	gc.Rotate(0.2)

	gc.DrawImage(source)
	gc.Restore()
	return nil
}

// Draw the image frame with certain parameters.

Draw the image frame with certain parameters .