upgrading libs
Этот коммит содержится в:
91
Godeps/Godeps.json
сгенерированный
91
Godeps/Godeps.json
сгенерированный
@@ -1,17 +1,7 @@
|
||||
{
|
||||
"ImportPath": "github.com/mattermost/platform",
|
||||
"GoVersion": "go1.4.2",
|
||||
"GoVersion": "go1.5.1",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go-uuid/uuid",
|
||||
"Comment": "null-15",
|
||||
"Rev": "35bc42037350f0078e3c974c6ea690f1926603ab"
|
||||
},
|
||||
{
|
||||
"ImportPath": "code.google.com/p/go.crypto/bcrypt",
|
||||
"Comment": "null-236",
|
||||
"Rev": "69e2a90ed92d03812364aeb947b7068dc42e561e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "code.google.com/p/log4go",
|
||||
"Comment": "go.weekly.2012-02-22-1",
|
||||
@@ -23,43 +13,47 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/braintree/manners",
|
||||
"Comment": "0.3.1-2-g5280e25",
|
||||
"Rev": "5280e250f2795914acbeb2bf3b55dd5a2d1fba52"
|
||||
"Comment": "0.4.0-9-g3fdfada",
|
||||
"Rev": "3fdfadabc96863ceec055bd73ab1e80324e72706"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||
"Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/disintegration/imaging",
|
||||
"Rev": "493653de80c32beeae336f3a3a3a125e7603459b"
|
||||
"Rev": "546cb3c5137b3f1232e123a26aa033aade6b3066"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/garyburd/redigo/internal",
|
||||
"Rev": "a47585eaae68b1d14b02940d2af1b9194f3caa9c"
|
||||
"Rev": "6ece6e0a09f28cc399b21550cbf37ab39ba63cce"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/garyburd/redigo/redis",
|
||||
"Rev": "a47585eaae68b1d14b02940d2af1b9194f3caa9c"
|
||||
"Rev": "6ece6e0a09f28cc399b21550cbf37ab39ba63cce"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-gorp/gorp",
|
||||
"Comment": "v1.7-65-g3c15f67",
|
||||
"Rev": "3c15f6739b94dc357e2797a7297a2853ec79f4fa"
|
||||
"Comment": "v1.7-146-gc391a3d",
|
||||
"Rev": "c391a3da75cf2003f4bf4763d0b5755c4500aef1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-sql-driver/mysql",
|
||||
"Comment": "v1.2-97-g0cc29e9",
|
||||
"Rev": "0cc29e9fe8e25c2c58cf47bcab566e029bbaa88b"
|
||||
"Comment": "v1.2-125-gd512f20",
|
||||
"Rev": "d512f204a577a4ab037a1816604c48c9c13210be"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/goamz/goamz/aws",
|
||||
"Rev": "ad637a587dd8314770a1084481dd7b5d4fa1232f"
|
||||
"Rev": "be371d06631a6ea076cccefc6654fa5c29be074d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/goamz/goamz/s3",
|
||||
"Rev": "ad637a587dd8314770a1084481dd7b5d4fa1232f"
|
||||
"Rev": "be371d06631a6ea076cccefc6654fa5c29be074d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/freetype",
|
||||
"Comment": "release-116-g41fa49a",
|
||||
"Rev": "41fa49aa5b23cc7c4082c9aaaf2da41e195602d9"
|
||||
"Comment": "release-120-gf29eb11",
|
||||
"Rev": "f29eb116deb328d02ee5c573f02d442ca67d5532"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/groupcache/lru",
|
||||
@@ -67,25 +61,33 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/context",
|
||||
"Rev": "215affda49addc4c8ef7e2534915df2c8c35c6cd"
|
||||
"Rev": "1c83b3eabd45b6d76072b66b746c20815fb2872d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/mux",
|
||||
"Rev": "94903de8c98a68d8b4483c529b26a5d146e386a2"
|
||||
"Rev": "9c068cf16d982f8bd444b8c352acbeec34c4fe5b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/websocket",
|
||||
"Rev": "6fd0f867fef40c540fa05c59f86396de10a632a6"
|
||||
"Rev": "361d4c0ffd78338ebe0a9e6320cdbe115d7dc026"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/lib/pq",
|
||||
"Comment": "go1.0-cutoff-56-gdc50b6a",
|
||||
"Rev": "dc50b6ad2d3ee836442cf3389009c7cd1e64bb43"
|
||||
"Comment": "go1.0-cutoff-61-g83c4f41",
|
||||
"Rev": "83c4f410d0aed80a0f44bac6a576a7f2435791f3"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mssola/user_agent",
|
||||
"Comment": "v0.4.1-4-ga163d6a",
|
||||
"Rev": "a163d6a569f1cd264d2f8b2bf3c5d04ace5995eb"
|
||||
"Comment": "v0.4.1-5-g783ec61",
|
||||
"Rev": "783ec61292aee3fc2f442ce740aa491e4849b794"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pborman/uuid",
|
||||
"Rev": "cccd189d45f7ac3368a0d127efb7f4d08ae0b655"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||
"Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/rwcarlsen/goexif/exif",
|
||||
@@ -97,27 +99,29 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/objx",
|
||||
"Rev": "cbeaeb16a013161a98496fad62933b1d21786672"
|
||||
"Rev": "1a9d0bb9f541897e62256577b352fdbc1fb4fd94"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/assert",
|
||||
"Rev": "dab07ac62d4905d3e48d17dc549c684ac3b7c15a"
|
||||
"Comment": "v1.0-83-gd797d25",
|
||||
"Rev": "d797d25e0fa6d53be3b1a216d24e868d6a1912ef"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/mock",
|
||||
"Rev": "dab07ac62d4905d3e48d17dc549c684ac3b7c15a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/throttled/throttled",
|
||||
"Rev": "fe4c91d601f05354c8a7feba917ab9d3b634f68d"
|
||||
"Comment": "v1.0-83-gd797d25",
|
||||
"Rev": "d797d25e0fa6d53be3b1a216d24e868d6a1912ef"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/vaughan0/go-ini",
|
||||
"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/bcrypt",
|
||||
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto/blowfish",
|
||||
"Rev": "74f810a0152f4c50a16195f6b9ff44afc35594e8"
|
||||
"Rev": "beef0f4390813b96e8e68fd78570396d0f4751fc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/image/bmp",
|
||||
@@ -137,8 +141,13 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/fsnotify.v1",
|
||||
"Comment": "v1.2.0",
|
||||
"Rev": "96c060f6a6b7e0d6f75fddd10efeaca3e5d1bcb0"
|
||||
"Comment": "v1.2.5",
|
||||
"Rev": "2cdd39bd6129c6a49c74fb07fb9d77ba1271c572"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/throttled/throttled.v1",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "74e328a1af88a9b54f9eca1397d74ad98572a6df"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/00changelog.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/00changelog.i
сгенерированный
поставляемый
Двоичный файл не отображается.
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/branch
сгенерированный
поставляемый
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/branch
сгенерированный
поставляемый
@@ -1 +0,0 @@
|
||||
default
|
||||
2
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/cache/branch2-served
сгенерированный
поставляемый
2
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/cache/branch2-served
сгенерированный
поставляемый
@@ -1,2 +0,0 @@
|
||||
46c3056cafbb4da11c4087a892c7d2bfa4224a8f 128
|
||||
46c3056cafbb4da11c4087a892c7d2bfa4224a8f o default
|
||||
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/cache/rbc-names-v1
сгенерированный
поставляемый
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/cache/rbc-names-v1
сгенерированный
поставляемый
@@ -1 +0,0 @@
|
||||
default
|
||||
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/cache/rbc-revs-v1
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/cache/rbc-revs-v1
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/dirstate
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/dirstate
сгенерированный
поставляемый
Двоичный файл не отображается.
14
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/hgrc
сгенерированный
поставляемый
14
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/hgrc
сгенерированный
поставляемый
@@ -1,14 +0,0 @@
|
||||
# example repository config (see "hg help config" for more info)
|
||||
[paths]
|
||||
default = https://code.google.com/p/freetype-go/
|
||||
|
||||
# path aliases to other clones of this repo in URLs or filesystem paths
|
||||
# (see "hg help config.paths" for more info)
|
||||
#
|
||||
# default-push = ssh://jdoe@example.net/hg/jdoes-fork
|
||||
# my-fork = ssh://jdoe@example.net/hg/jdoes-fork
|
||||
# my-clone = /home/jdoe/jdoes-clone
|
||||
|
||||
[ui]
|
||||
# name and email (local to this repository, optional), e.g.
|
||||
# username = Jane Doe <jdoe@example.com>
|
||||
4
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/requires
сгенерированный
поставляемый
4
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/requires
сгенерированный
поставляемый
@@ -1,4 +0,0 @@
|
||||
dotencode
|
||||
fncache
|
||||
revlogv1
|
||||
store
|
||||
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/00changelog.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/00changelog.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/00manifest.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/00manifest.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_a_u_t_h_o_r_s.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_a_u_t_h_o_r_s.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_c_o_n_t_r_i_b_u_t_o_r_s.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_c_o_n_t_r_i_b_u_t_o_r_s.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_l_i_c_e_n_s_e.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_l_i_c_e_n_s_e.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_makefile.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_makefile.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_r_e_a_d_m_e.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/_r_e_a_d_m_e.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/cmd/print-glyph-points/main.c.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/cmd/print-glyph-points/main.c.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/freetype/main.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/freetype/main.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/gamma/main.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/gamma/main.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/raster/main.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/raster/main.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/round/main.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/round/main.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/truetype/main.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/example/truetype/main.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/_makefile.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/_makefile.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/freetype.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/freetype.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/freetype__test.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/freetype__test.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/_makefile.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/_makefile.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/geom.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/geom.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/paint.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/paint.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/raster.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/raster.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/stroke.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/raster/stroke.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/_makefile.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/_makefile.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/glyph.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/glyph.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/hint.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/hint.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/hint__test.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/hint__test.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/opcodes.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/opcodes.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/truetype.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/truetype.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/truetype__test.go.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/freetype/truetype/truetype__test.go.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/lib/codereview/codereview.cfg.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/lib/codereview/codereview.cfg.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/licenses/ftl.txt.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/licenses/ftl.txt.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/licenses/gpl.txt.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/licenses/gpl.txt.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/_c_o_p_y_i_n_g.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/_c_o_p_y_i_n_g.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/_r_e_a_d_m_e.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/_r_e_a_d_m_e.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luximr.ttf.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luximr.ttf.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luximr.ttx.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luximr.ttx.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxirr.ttf.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxirr.ttf.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxirr.ttx.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxirr.ttx.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr-12pt-sans-hinting.txt.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr-12pt-sans-hinting.txt.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr-12pt-with-hinting.txt.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr-12pt-with-hinting.txt.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr.ttf.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr.ttf.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr.ttx.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/luxi-fonts/luxisr.ttx.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/_c_o_p_y_i_n_g.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/_c_o_p_y_i_n_g.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/_r_e_a_d_m_e.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/_r_e_a_d_m_e.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luximr.ttf.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luximr.ttf.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luximr.ttx.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luximr.ttx.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxirr.ttf.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxirr.ttf.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxirr.ttx.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxirr.ttx.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr-12pt-sans-hinting.txt.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr-12pt-sans-hinting.txt.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr-12pt-with-hinting.txt.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr-12pt-with-hinting.txt.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr.ttf.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr.ttf.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr.ttx.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/luxisr.ttx.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/make-other-hinting-txts.sh.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/testdata/make-other-hinting-txts.sh.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/~2ehgignore.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/~2ehgignore.i
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/~2ehgtags.i
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/data/~2ehgtags.i
сгенерированный
поставляемый
Двоичный файл не отображается.
52
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/fncache
сгенерированный
поставляемый
52
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/fncache
сгенерированный
поставляемый
@@ -1,52 +0,0 @@
|
||||
data/testdata/luxisr.ttf.i
|
||||
data/testdata/luximr.ttx.i
|
||||
data/freetype/raster/geom.go.i
|
||||
data/AUTHORS.i
|
||||
data/CONTRIBUTORS.i
|
||||
data/freetype/truetype/Makefile.i
|
||||
data/testdata/luxisr-12pt-with-hinting.txt.i
|
||||
data/luxi-fonts/luxisr-12pt-sans-hinting.txt.i
|
||||
data/example/freetype/main.go.i
|
||||
data/luxi-fonts/luxirr.ttf.i
|
||||
data/testdata/COPYING.i
|
||||
data/example/gamma/main.go.i
|
||||
data/freetype/Makefile.i
|
||||
data/testdata/luxirr.ttx.i
|
||||
data/freetype/freetype_test.go.i
|
||||
data/example/truetype/main.go.i
|
||||
data/Makefile.i
|
||||
data/freetype/freetype.go.i
|
||||
data/luxi-fonts/luximr.ttx.i
|
||||
data/example/round/main.go.i
|
||||
data/freetype/raster/paint.go.i
|
||||
data/luxi-fonts/luximr.ttf.i
|
||||
data/luxi-fonts/luxisr.ttx.i
|
||||
data/example/raster/main.go.i
|
||||
data/lib/codereview/codereview.cfg.i
|
||||
data/testdata/luximr.ttf.i
|
||||
data/luxi-fonts/README.i
|
||||
data/testdata/luxisr.ttx.i
|
||||
data/luxi-fonts/luxisr-12pt-with-hinting.txt.i
|
||||
data/freetype/truetype/hint_test.go.i
|
||||
data/testdata/make-other-hinting-txts.sh.i
|
||||
data/luxi-fonts/COPYING.i
|
||||
data/licenses/ftl.txt.i
|
||||
data/freetype/truetype/opcodes.go.i
|
||||
data/.hgignore.i
|
||||
data/freetype/truetype/truetype.go.i
|
||||
data/testdata/luxirr.ttf.i
|
||||
data/freetype/truetype/truetype_test.go.i
|
||||
data/LICENSE.i
|
||||
data/freetype/raster/stroke.go.i
|
||||
data/luxi-fonts/luxirr.ttx.i
|
||||
data/licenses/gpl.txt.i
|
||||
data/freetype/raster/raster.go.i
|
||||
data/freetype/truetype/hint.go.i
|
||||
data/testdata/luxisr-12pt-sans-hinting.txt.i
|
||||
data/.hgtags.i
|
||||
data/README.i
|
||||
data/freetype/raster/Makefile.i
|
||||
data/testdata/README.i
|
||||
data/luxi-fonts/luxisr.ttf.i
|
||||
data/cmd/print-glyph-points/main.c.i
|
||||
data/freetype/truetype/glyph.go.i
|
||||
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/phaseroots
сгенерированный
поставляемый
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/phaseroots
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/undo
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/undo
сгенерированный
поставляемый
Двоичный файл не отображается.
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/undo.backupfiles
сгенерированный
поставляемый
Двоичные данные
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/undo.backupfiles
сгенерированный
поставляемый
Двоичный файл не отображается.
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/undo.phaseroots
сгенерированный
поставляемый
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/store/undo.phaseroots
сгенерированный
поставляемый
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.bookmarks
сгенерированный
поставляемый
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.bookmarks
сгенерированный
поставляемый
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.branch
сгенерированный
поставляемый
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.branch
сгенерированный
поставляемый
@@ -1 +0,0 @@
|
||||
default
|
||||
3
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.desc
сгенерированный
поставляемый
3
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.desc
сгенерированный
поставляемый
@@ -1,3 +0,0 @@
|
||||
0
|
||||
pull
|
||||
https://code.google.com/p/freetype-go/
|
||||
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.dirstate
сгенерированный
поставляемый
0
Godeps/_workspace/src/code.google.com/p/freetype-go/.hg/undo.dirstate
сгенерированный
поставляемый
35
Godeps/_workspace/src/code.google.com/p/freetype-go/.hgignore
сгенерированный
поставляемый
35
Godeps/_workspace/src/code.google.com/p/freetype-go/.hgignore
сгенерированный
поставляемый
@@ -1,35 +0,0 @@
|
||||
syntax:glob
|
||||
.DS_Store
|
||||
.git
|
||||
.gitignore
|
||||
*.[568ao]
|
||||
*.a[568o]
|
||||
*.so
|
||||
*.pyc
|
||||
._*
|
||||
.nfs.*
|
||||
[568a].out
|
||||
*~
|
||||
*.orig
|
||||
*.rej
|
||||
*.exe
|
||||
.*.swp
|
||||
core
|
||||
*.cgo*.go
|
||||
*.cgo*.c
|
||||
_cgo_*
|
||||
_obj
|
||||
_test
|
||||
_testmain.go
|
||||
build.out
|
||||
test.out
|
||||
goinstall.log
|
||||
last-change
|
||||
VERSION.cache
|
||||
out.png
|
||||
|
||||
syntax:regexp
|
||||
^bin/
|
||||
^pkg/
|
||||
^src/cmd/(.*)/6?\1$
|
||||
^.*/core.[0-9]*$
|
||||
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hgtags
сгенерированный
поставляемый
1
Godeps/_workspace/src/code.google.com/p/freetype-go/.hgtags
сгенерированный
поставляемый
@@ -1 +0,0 @@
|
||||
96d0c07904d187405d9f34a3654ce06b0238f31d release
|
||||
17
Godeps/_workspace/src/code.google.com/p/freetype-go/AUTHORS
сгенерированный
поставляемый
17
Godeps/_workspace/src/code.google.com/p/freetype-go/AUTHORS
сгенерированный
поставляемый
@@ -1,17 +0,0 @@
|
||||
# This is the official list of Freetype-Go authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
#
|
||||
# Freetype-Go is derived from Freetype, which is written in C. The latter
|
||||
# is copyright 1996-2010 David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Google Inc.
|
||||
Jeff R. Allen <jra@nella.org>
|
||||
Rémy Oudompheng <oudomphe@phare.normalesup.org>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
||||
35
Godeps/_workspace/src/code.google.com/p/freetype-go/CONTRIBUTORS
сгенерированный
поставляемый
35
Godeps/_workspace/src/code.google.com/p/freetype-go/CONTRIBUTORS
сгенерированный
поставляемый
@@ -1,35 +0,0 @@
|
||||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the Freetype-Go repository.
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees are listed here
|
||||
# but not in AUTHORS, because Google holds the copyright.
|
||||
#
|
||||
# The submission process automatically checks to make sure
|
||||
# that people submitting code are listed in this file (by email address).
|
||||
#
|
||||
# Names should be added to this file only after verifying that
|
||||
# the individual or the individual's organization has agreed to
|
||||
# the appropriate Contributor License Agreement, found here:
|
||||
#
|
||||
# http://code.google.com/legal/individual-cla-v1.0.html
|
||||
# http://code.google.com/legal/corporate-cla-v1.0.html
|
||||
#
|
||||
# The agreement for individuals can be filled out on the web.
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file, depending on whether the
|
||||
# individual or corporate CLA was used.
|
||||
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Andrew Gerrand <adg@golang.org>
|
||||
Jeff R. Allen <jra@nella.org> <jeff.allen@gmail.com>
|
||||
Nigel Tao <nigeltao@golang.org>
|
||||
Rémy Oudompheng <oudomphe@phare.normalesup.org> <remyoudompheng@gmail.com>
|
||||
Rob Pike <r@golang.org>
|
||||
Roger Peppe <rogpeppe@gmail.com>
|
||||
Russ Cox <rsc@golang.org>
|
||||
12
Godeps/_workspace/src/code.google.com/p/freetype-go/LICENSE
сгенерированный
поставляемый
12
Godeps/_workspace/src/code.google.com/p/freetype-go/LICENSE
сгенерированный
поставляемый
@@ -1,12 +0,0 @@
|
||||
Use of the Freetype-Go software is subject to your choice of exactly one of
|
||||
the following two licenses:
|
||||
* The FreeType License, which is similar to the original BSD license with
|
||||
an advertising clause, or
|
||||
* The GNU General Public License (GPL), version 2 or later.
|
||||
|
||||
The text of these licenses are available in the licenses/ftl.txt and the
|
||||
licenses/gpl.txt files respectively. They are also available at
|
||||
http://freetype.sourceforge.net/license.html
|
||||
|
||||
The Luxi fonts in the testdata directory are licensed separately. See the
|
||||
testdata/COPYING file for details.
|
||||
22
Godeps/_workspace/src/code.google.com/p/freetype-go/README
сгенерированный
поставляемый
22
Godeps/_workspace/src/code.google.com/p/freetype-go/README
сгенерированный
поставляемый
@@ -1,22 +0,0 @@
|
||||
This is a port of the Freetype font rasterizer (www.freetype.org) to the Go
|
||||
programming language (golang.org).
|
||||
|
||||
To download and install from source:
|
||||
$ go get code.google.com/p/freetype-go/freetype
|
||||
|
||||
It is an incomplete port:
|
||||
* It only supports TrueType fonts, and not Type 1 fonts nor bitmap fonts.
|
||||
* It only supports the Unicode encoding.
|
||||
|
||||
There are also some implementation differences:
|
||||
* It uses a 24.8 fixed point co-ordinate system everywhere internally,
|
||||
as opposed to the original Freetype's mix of 26.6 (or 10.6 for 16-bit
|
||||
systems) in some places, and 24.8 in the "smooth" rasterizer.
|
||||
|
||||
Freetype-Go is derived from Freetype, which is written in C. Freetype is
|
||||
copyright 1996-2010 David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
Freetype-Go is copyright The Freetype-Go Authors, who are listed in the
|
||||
AUTHORS file.
|
||||
|
||||
The Freetype-Go homepage is http://code.google.com/p/freetype-go/
|
||||
|
||||
87
Godeps/_workspace/src/code.google.com/p/freetype-go/cmd/print-glyph-points/main.c
сгенерированный
поставляемый
87
Godeps/_workspace/src/code.google.com/p/freetype-go/cmd/print-glyph-points/main.c
сгенерированный
поставляемый
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
gcc main.c -I/usr/include/freetype2 -lfreetype && ./a.out 12 ../../testdata/luxisr.ttf with_hinting
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
void usage(char** argv) {
|
||||
fprintf(stderr, "usage: %s font_size font_file [with_hinting|sans_hinting]\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
FT_Error error;
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Glyph_Metrics* m;
|
||||
FT_Outline* o;
|
||||
FT_Int major, minor, patch;
|
||||
int i, j, font_size, no_hinting;
|
||||
|
||||
if (argc != 4) {
|
||||
usage(argv);
|
||||
return 1;
|
||||
}
|
||||
font_size = atoi(argv[1]);
|
||||
if (font_size <= 0) {
|
||||
fprintf(stderr, "invalid font_size\n");
|
||||
usage(argv);
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(argv[3], "with_hinting")) {
|
||||
no_hinting = 0;
|
||||
} else if (!strcmp(argv[3], "sans_hinting")) {
|
||||
no_hinting = 1;
|
||||
} else {
|
||||
fprintf(stderr, "neither \"with_hinting\" nor \"sans_hinting\"\n");
|
||||
usage(argv);
|
||||
return 1;
|
||||
};
|
||||
error = FT_Init_FreeType(&library);
|
||||
if (error) {
|
||||
fprintf(stderr, "FT_Init_FreeType: error #%d\n", error);
|
||||
return 1;
|
||||
}
|
||||
FT_Library_Version(library, &major, &minor, &patch);
|
||||
printf("freetype version %d.%d.%d\n", major, minor, patch);
|
||||
error = FT_New_Face(library, argv[2], 0, &face);
|
||||
if (error) {
|
||||
fprintf(stderr, "FT_New_Face: error #%d\n", error);
|
||||
return 1;
|
||||
}
|
||||
error = FT_Set_Char_Size(face, 0, font_size*64, 0, 0);
|
||||
if (error) {
|
||||
fprintf(stderr, "FT_Set_Char_Size: error #%d\n", error);
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < face->num_glyphs; i++) {
|
||||
error = FT_Load_Glyph(face, i, no_hinting ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
fprintf(stderr, "FT_Load_Glyph: glyph %d: error #%d\n", i, error);
|
||||
return 1;
|
||||
}
|
||||
if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) {
|
||||
fprintf(stderr, "glyph format for glyph %d is not FT_GLYPH_FORMAT_OUTLINE\n", i);
|
||||
return 1;
|
||||
}
|
||||
m = &face->glyph->metrics;
|
||||
/* Print what Go calls the AdvanceWidth, and then: XMin, YMin, XMax, YMax. */
|
||||
printf("%ld %ld %ld %ld %ld;",
|
||||
m->horiAdvance,
|
||||
m->horiBearingX,
|
||||
m->horiBearingY - m->height,
|
||||
m->horiBearingX + m->width,
|
||||
m->horiBearingY);
|
||||
/* Print the glyph points. */
|
||||
o = &face->glyph->outline;
|
||||
for (j = 0; j < o->n_points; j++) {
|
||||
if (j != 0) {
|
||||
printf(", ");
|
||||
}
|
||||
printf("%ld %ld %d", o->points[j].x, o->points[j].y, o->tags[j] & 0x01);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
143
Godeps/_workspace/src/code.google.com/p/freetype-go/example/freetype/main.go
сгенерированный
поставляемый
143
Godeps/_workspace/src/code.google.com/p/freetype-go/example/freetype/main.go
сгенерированный
поставляемый
@@ -1,143 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"code.google.com/p/freetype-go/freetype"
|
||||
)
|
||||
|
||||
var (
|
||||
dpi = flag.Float64("dpi", 72, "screen resolution in Dots Per Inch")
|
||||
fontfile = flag.String("fontfile", "../../testdata/luxisr.ttf", "filename of the ttf font")
|
||||
hinting = flag.String("hinting", "none", "none | full")
|
||||
size = flag.Float64("size", 12, "font size in points")
|
||||
spacing = flag.Float64("spacing", 1.5, "line spacing (e.g. 2 means double spaced)")
|
||||
wonb = flag.Bool("whiteonblack", false, "white text on a black background")
|
||||
)
|
||||
|
||||
var text = []string{
|
||||
"’Twas brillig, and the slithy toves",
|
||||
"Did gyre and gimble in the wabe;",
|
||||
"All mimsy were the borogoves,",
|
||||
"And the mome raths outgrabe.",
|
||||
"",
|
||||
"“Beware the Jabberwock, my son!",
|
||||
"The jaws that bite, the claws that catch!",
|
||||
"Beware the Jubjub bird, and shun",
|
||||
"The frumious Bandersnatch!”",
|
||||
"",
|
||||
"He took his vorpal sword in hand:",
|
||||
"Long time the manxome foe he sought—",
|
||||
"So rested he by the Tumtum tree,",
|
||||
"And stood awhile in thought.",
|
||||
"",
|
||||
"And as in uffish thought he stood,",
|
||||
"The Jabberwock, with eyes of flame,",
|
||||
"Came whiffling through the tulgey wood,",
|
||||
"And burbled as it came!",
|
||||
"",
|
||||
"One, two! One, two! and through and through",
|
||||
"The vorpal blade went snicker-snack!",
|
||||
"He left it dead, and with its head",
|
||||
"He went galumphing back.",
|
||||
"",
|
||||
"“And hast thou slain the Jabberwock?",
|
||||
"Come to my arms, my beamish boy!",
|
||||
"O frabjous day! Callooh! Callay!”",
|
||||
"He chortled in his joy.",
|
||||
"",
|
||||
"’Twas brillig, and the slithy toves",
|
||||
"Did gyre and gimble in the wabe;",
|
||||
"All mimsy were the borogoves,",
|
||||
"And the mome raths outgrabe.",
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
// Read the font data.
|
||||
fontBytes, err := ioutil.ReadFile(*fontfile)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
font, err := freetype.ParseFont(fontBytes)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Initialize the context.
|
||||
fg, bg := image.Black, image.White
|
||||
ruler := color.RGBA{0xdd, 0xdd, 0xdd, 0xff}
|
||||
if *wonb {
|
||||
fg, bg = image.White, image.Black
|
||||
ruler = color.RGBA{0x22, 0x22, 0x22, 0xff}
|
||||
}
|
||||
rgba := image.NewRGBA(image.Rect(0, 0, 640, 480))
|
||||
draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src)
|
||||
c := freetype.NewContext()
|
||||
c.SetDPI(*dpi)
|
||||
c.SetFont(font)
|
||||
c.SetFontSize(*size)
|
||||
c.SetClip(rgba.Bounds())
|
||||
c.SetDst(rgba)
|
||||
c.SetSrc(fg)
|
||||
switch *hinting {
|
||||
default:
|
||||
c.SetHinting(freetype.NoHinting)
|
||||
case "full":
|
||||
c.SetHinting(freetype.FullHinting)
|
||||
}
|
||||
|
||||
// Draw the guidelines.
|
||||
for i := 0; i < 200; i++ {
|
||||
rgba.Set(10, 10+i, ruler)
|
||||
rgba.Set(10+i, 10, ruler)
|
||||
}
|
||||
|
||||
// Draw the text.
|
||||
pt := freetype.Pt(10, 10+int(c.PointToFix32(*size)>>8))
|
||||
for _, s := range text {
|
||||
_, err = c.DrawString(s, pt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
pt.Y += c.PointToFix32(*size * *spacing)
|
||||
}
|
||||
|
||||
// Save that RGBA image to disk.
|
||||
f, err := os.Create("out.png")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
b := bufio.NewWriter(f)
|
||||
err = png.Encode(b, rgba)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = b.Flush()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Wrote out.png OK.")
|
||||
}
|
||||
79
Godeps/_workspace/src/code.google.com/p/freetype-go/example/gamma/main.go
сгенерированный
поставляемый
79
Godeps/_workspace/src/code.google.com/p/freetype-go/example/gamma/main.go
сгенерированный
поставляемый
@@ -1,79 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"code.google.com/p/freetype-go/freetype/raster"
|
||||
)
|
||||
|
||||
func p(x, y int) raster.Point {
|
||||
return raster.Point{
|
||||
X: raster.Fix32(x * 256),
|
||||
Y: raster.Fix32(y * 256),
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Draw a rounded corner that is one pixel wide.
|
||||
r := raster.NewRasterizer(50, 50)
|
||||
r.Start(p(5, 5))
|
||||
r.Add1(p(5, 25))
|
||||
r.Add2(p(5, 45), p(25, 45))
|
||||
r.Add1(p(45, 45))
|
||||
r.Add1(p(45, 44))
|
||||
r.Add1(p(26, 44))
|
||||
r.Add2(p(6, 44), p(6, 24))
|
||||
r.Add1(p(6, 5))
|
||||
r.Add1(p(5, 5))
|
||||
|
||||
// Rasterize that curve multiple times at different gammas.
|
||||
const (
|
||||
w = 600
|
||||
h = 200
|
||||
)
|
||||
rgba := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
draw.Draw(rgba, image.Rect(0, 0, w, h/2), image.Black, image.ZP, draw.Src)
|
||||
draw.Draw(rgba, image.Rect(0, h/2, w, h), image.White, image.ZP, draw.Src)
|
||||
mask := image.NewAlpha(image.Rect(0, 0, 50, 50))
|
||||
painter := raster.NewAlphaSrcPainter(mask)
|
||||
gammas := []float64{1.0 / 10.0, 1.0 / 3.0, 1.0 / 2.0, 2.0 / 3.0, 4.0 / 5.0, 1.0, 5.0 / 4.0, 3.0 / 2.0, 2.0, 3.0, 10.0}
|
||||
for i, g := range gammas {
|
||||
draw.Draw(mask, mask.Bounds(), image.Transparent, image.ZP, draw.Src)
|
||||
r.Rasterize(raster.NewGammaCorrectionPainter(painter, g))
|
||||
x, y := 50*i+25, 25
|
||||
draw.DrawMask(rgba, image.Rect(x, y, x+50, y+50), image.White, image.ZP, mask, image.ZP, draw.Over)
|
||||
y += 100
|
||||
draw.DrawMask(rgba, image.Rect(x, y, x+50, y+50), image.Black, image.ZP, mask, image.ZP, draw.Over)
|
||||
}
|
||||
|
||||
// Save that RGBA image to disk.
|
||||
f, err := os.Create("out.png")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
b := bufio.NewWriter(f)
|
||||
err = png.Encode(b, rgba)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = b.Flush()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Wrote out.png OK.")
|
||||
}
|
||||
178
Godeps/_workspace/src/code.google.com/p/freetype-go/example/raster/main.go
сгенерированный
поставляемый
178
Godeps/_workspace/src/code.google.com/p/freetype-go/example/raster/main.go
сгенерированный
поставляемый
@@ -1,178 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"code.google.com/p/freetype-go/freetype/raster"
|
||||
)
|
||||
|
||||
type node struct {
|
||||
x, y, degree int
|
||||
}
|
||||
|
||||
// These contours "outside" and "inside" are from the `A' glyph from the Droid
|
||||
// Serif Regular font.
|
||||
|
||||
var outside = []node{
|
||||
node{414, 489, 1},
|
||||
node{336, 274, 2},
|
||||
node{327, 250, 0},
|
||||
node{322, 226, 2},
|
||||
node{317, 203, 0},
|
||||
node{317, 186, 2},
|
||||
node{317, 134, 0},
|
||||
node{350, 110, 2},
|
||||
node{384, 86, 0},
|
||||
node{453, 86, 1},
|
||||
node{500, 86, 1},
|
||||
node{500, 0, 1},
|
||||
node{0, 0, 1},
|
||||
node{0, 86, 1},
|
||||
node{39, 86, 2},
|
||||
node{69, 86, 0},
|
||||
node{90, 92, 2},
|
||||
node{111, 99, 0},
|
||||
node{128, 117, 2},
|
||||
node{145, 135, 0},
|
||||
node{160, 166, 2},
|
||||
node{176, 197, 0},
|
||||
node{195, 246, 1},
|
||||
node{649, 1462, 1},
|
||||
node{809, 1462, 1},
|
||||
node{1272, 195, 2},
|
||||
node{1284, 163, 0},
|
||||
node{1296, 142, 2},
|
||||
node{1309, 121, 0},
|
||||
node{1326, 108, 2},
|
||||
node{1343, 96, 0},
|
||||
node{1365, 91, 2},
|
||||
node{1387, 86, 0},
|
||||
node{1417, 86, 1},
|
||||
node{1444, 86, 1},
|
||||
node{1444, 0, 1},
|
||||
node{881, 0, 1},
|
||||
node{881, 86, 1},
|
||||
node{928, 86, 2},
|
||||
node{1051, 86, 0},
|
||||
node{1051, 184, 2},
|
||||
node{1051, 201, 0},
|
||||
node{1046, 219, 2},
|
||||
node{1042, 237, 0},
|
||||
node{1034, 260, 1},
|
||||
node{952, 489, 1},
|
||||
node{414, 489, -1},
|
||||
}
|
||||
|
||||
var inside = []node{
|
||||
node{686, 1274, 1},
|
||||
node{453, 592, 1},
|
||||
node{915, 592, 1},
|
||||
node{686, 1274, -1},
|
||||
}
|
||||
|
||||
func p(n node) raster.Point {
|
||||
x, y := 20+n.x/4, 380-n.y/4
|
||||
return raster.Point{
|
||||
X: raster.Fix32(x * 256),
|
||||
Y: raster.Fix32(y * 256),
|
||||
}
|
||||
}
|
||||
|
||||
func contour(r *raster.Rasterizer, ns []node) {
|
||||
if len(ns) == 0 {
|
||||
return
|
||||
}
|
||||
i := 0
|
||||
r.Start(p(ns[i]))
|
||||
for {
|
||||
switch ns[i].degree {
|
||||
case -1:
|
||||
// -1 signifies end-of-contour.
|
||||
return
|
||||
case 1:
|
||||
i += 1
|
||||
r.Add1(p(ns[i]))
|
||||
case 2:
|
||||
i += 2
|
||||
r.Add2(p(ns[i-1]), p(ns[i]))
|
||||
default:
|
||||
panic("bad degree")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func showNodes(m *image.RGBA, ns []node) {
|
||||
for _, n := range ns {
|
||||
p := p(n)
|
||||
x, y := int(p.X)/256, int(p.Y)/256
|
||||
if !(image.Point{x, y}).In(m.Bounds()) {
|
||||
continue
|
||||
}
|
||||
var c color.Color
|
||||
switch n.degree {
|
||||
case 0:
|
||||
c = color.RGBA{0, 255, 255, 255}
|
||||
case 1:
|
||||
c = color.RGBA{255, 0, 0, 255}
|
||||
case 2:
|
||||
c = color.RGBA{255, 0, 0, 255}
|
||||
}
|
||||
if c != nil {
|
||||
m.Set(x, y, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Rasterize the contours to a mask image.
|
||||
const (
|
||||
w = 400
|
||||
h = 400
|
||||
)
|
||||
r := raster.NewRasterizer(w, h)
|
||||
contour(r, outside)
|
||||
contour(r, inside)
|
||||
mask := image.NewAlpha(image.Rect(0, 0, w, h))
|
||||
p := raster.NewAlphaSrcPainter(mask)
|
||||
r.Rasterize(p)
|
||||
|
||||
// Draw the mask image (in gray) onto an RGBA image.
|
||||
rgba := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
gray := image.NewUniform(color.Alpha{0x1f})
|
||||
draw.Draw(rgba, rgba.Bounds(), image.Black, image.ZP, draw.Src)
|
||||
draw.DrawMask(rgba, rgba.Bounds(), gray, image.ZP, mask, image.ZP, draw.Over)
|
||||
showNodes(rgba, outside)
|
||||
showNodes(rgba, inside)
|
||||
|
||||
// Save that RGBA image to disk.
|
||||
f, err := os.Create("out.png")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
b := bufio.NewWriter(f)
|
||||
err = png.Encode(b, rgba)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = b.Flush()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Wrote out.png OK.")
|
||||
}
|
||||
96
Godeps/_workspace/src/code.google.com/p/freetype-go/example/round/main.go
сгенерированный
поставляемый
96
Godeps/_workspace/src/code.google.com/p/freetype-go/example/round/main.go
сгенерированный
поставляемый
@@ -1,96 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
// This program visualizes the quadratic approximation to the circle, used to
|
||||
// implement round joins when stroking paths. The approximation is used in the
|
||||
// stroking code for arcs between 0 and 45 degrees, but is visualized here
|
||||
// between 0 and 90 degrees. The discrepancy between the approximation and the
|
||||
// true circle is clearly visible at angles above 65 degrees.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
"code.google.com/p/freetype-go/freetype/raster"
|
||||
)
|
||||
|
||||
func main() {
|
||||
const (
|
||||
n = 17
|
||||
r = 256 * 80
|
||||
)
|
||||
s := raster.Fix32(r * math.Sqrt(2) / 2)
|
||||
t := raster.Fix32(r * math.Tan(math.Pi/8))
|
||||
|
||||
m := image.NewRGBA(image.Rect(0, 0, 800, 600))
|
||||
draw.Draw(m, m.Bounds(), image.NewUniform(color.RGBA{63, 63, 63, 255}), image.ZP, draw.Src)
|
||||
mp := raster.NewRGBAPainter(m)
|
||||
mp.SetColor(image.Black)
|
||||
z := raster.NewRasterizer(800, 600)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
cx := raster.Fix32(25600 + 51200*(i%4))
|
||||
cy := raster.Fix32(2560 + 32000*(i/4))
|
||||
c := raster.Point{X: cx, Y: cy}
|
||||
theta := math.Pi * (0.5 + 0.5*float64(i)/(n-1))
|
||||
dx := raster.Fix32(r * math.Cos(theta))
|
||||
dy := raster.Fix32(r * math.Sin(theta))
|
||||
d := raster.Point{X: dx, Y: dy}
|
||||
// Draw a quarter-circle approximated by two quadratic segments,
|
||||
// with each segment spanning 45 degrees.
|
||||
z.Start(c)
|
||||
z.Add1(c.Add(raster.Point{X: r, Y: 0}))
|
||||
z.Add2(c.Add(raster.Point{X: r, Y: t}), c.Add(raster.Point{X: s, Y: s}))
|
||||
z.Add2(c.Add(raster.Point{X: t, Y: r}), c.Add(raster.Point{X: 0, Y: r}))
|
||||
// Add another quadratic segment whose angle ranges between 0 and 90 degrees.
|
||||
// For an explanation of the magic constants 22, 150, 181 and 256, read the
|
||||
// comments in the freetype/raster package.
|
||||
dot := 256 * d.Dot(raster.Point{X: 0, Y: r}) / (r * r)
|
||||
multiple := raster.Fix32(150 - 22*(dot-181)/(256-181))
|
||||
z.Add2(c.Add(raster.Point{X: dx, Y: r + dy}.Mul(multiple)), c.Add(d))
|
||||
// Close the curve.
|
||||
z.Add1(c)
|
||||
}
|
||||
z.Rasterize(mp)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
cx := raster.Fix32(25600 + 51200*(i%4))
|
||||
cy := raster.Fix32(2560 + 32000*(i/4))
|
||||
for j := 0; j < n; j++ {
|
||||
theta := math.Pi * float64(j) / (n - 1)
|
||||
dx := raster.Fix32(r * math.Cos(theta))
|
||||
dy := raster.Fix32(r * math.Sin(theta))
|
||||
m.Set(int((cx+dx)/256), int((cy+dy)/256), color.RGBA{255, 255, 0, 255})
|
||||
}
|
||||
}
|
||||
|
||||
// Save that RGBA image to disk.
|
||||
f, err := os.Create("out.png")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
b := bufio.NewWriter(f)
|
||||
err = png.Encode(b, m)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = b.Flush()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println("Wrote out.png OK.")
|
||||
}
|
||||
73
Godeps/_workspace/src/code.google.com/p/freetype-go/example/truetype/main.go
сгенерированный
поставляемый
73
Godeps/_workspace/src/code.google.com/p/freetype-go/example/truetype/main.go
сгенерированный
поставляемый
@@ -1,73 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"code.google.com/p/freetype-go/freetype/truetype"
|
||||
)
|
||||
|
||||
var fontfile = flag.String("fontfile", "../../testdata/luxisr.ttf", "filename of the ttf font")
|
||||
|
||||
func printBounds(b truetype.Bounds) {
|
||||
fmt.Printf("XMin:%d YMin:%d XMax:%d YMax:%d\n", b.XMin, b.YMin, b.XMax, b.YMax)
|
||||
}
|
||||
|
||||
func printGlyph(g *truetype.GlyphBuf) {
|
||||
printBounds(g.B)
|
||||
fmt.Print("Points:\n---\n")
|
||||
e := 0
|
||||
for i, p := range g.Point {
|
||||
fmt.Printf("%4d, %4d", p.X, p.Y)
|
||||
if p.Flags&0x01 != 0 {
|
||||
fmt.Print(" on\n")
|
||||
} else {
|
||||
fmt.Print(" off\n")
|
||||
}
|
||||
if i+1 == int(g.End[e]) {
|
||||
fmt.Print("---\n")
|
||||
e++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
fmt.Printf("Loading fontfile %q\n", *fontfile)
|
||||
b, err := ioutil.ReadFile(*fontfile)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
font, err := truetype.Parse(b)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
fupe := font.FUnitsPerEm()
|
||||
printBounds(font.Bounds(fupe))
|
||||
fmt.Printf("FUnitsPerEm:%d\n\n", fupe)
|
||||
|
||||
c0, c1 := 'A', 'V'
|
||||
|
||||
i0 := font.Index(c0)
|
||||
hm := font.HMetric(fupe, i0)
|
||||
g := truetype.NewGlyphBuf()
|
||||
err = g.Load(font, fupe, i0, truetype.NoHinting)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("'%c' glyph\n", c0)
|
||||
fmt.Printf("AdvanceWidth:%d LeftSideBearing:%d\n", hm.AdvanceWidth, hm.LeftSideBearing)
|
||||
printGlyph(g)
|
||||
i1 := font.Index(c1)
|
||||
fmt.Printf("\n'%c', '%c' Kerning:%d\n", c0, c1, font.Kerning(fupe, i0, i1))
|
||||
}
|
||||
349
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/freetype.go
сгенерированный
поставляемый
349
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/freetype.go
сгенерированный
поставляемый
@@ -1,349 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
// The freetype package provides a convenient API to draw text onto an image.
|
||||
// Use the freetype/raster and freetype/truetype packages for lower level
|
||||
// control over rasterization and TrueType parsing.
|
||||
package freetype
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"image/draw"
|
||||
|
||||
"code.google.com/p/freetype-go/freetype/raster"
|
||||
"code.google.com/p/freetype-go/freetype/truetype"
|
||||
)
|
||||
|
||||
// These constants determine the size of the glyph cache. The cache is keyed
|
||||
// primarily by the glyph index modulo nGlyphs, and secondarily by sub-pixel
|
||||
// position for the mask image. Sub-pixel positions are quantized to
|
||||
// nXFractions possible values in both the x and y directions.
|
||||
const (
|
||||
nGlyphs = 256
|
||||
nXFractions = 4
|
||||
nYFractions = 1
|
||||
)
|
||||
|
||||
// An entry in the glyph cache is keyed explicitly by the glyph index and
|
||||
// implicitly by the quantized x and y fractional offset. It maps to a mask
|
||||
// image and an offset.
|
||||
type cacheEntry struct {
|
||||
valid bool
|
||||
glyph truetype.Index
|
||||
advanceWidth raster.Fix32
|
||||
mask *image.Alpha
|
||||
offset image.Point
|
||||
}
|
||||
|
||||
// ParseFont just calls the Parse function from the freetype/truetype package.
|
||||
// It is provided here so that code that imports this package doesn't need
|
||||
// to also include the freetype/truetype package.
|
||||
func ParseFont(b []byte) (*truetype.Font, error) {
|
||||
return truetype.Parse(b)
|
||||
}
|
||||
|
||||
// Pt converts from a co-ordinate pair measured in pixels to a raster.Point
|
||||
// co-ordinate pair measured in raster.Fix32 units.
|
||||
func Pt(x, y int) raster.Point {
|
||||
return raster.Point{
|
||||
X: raster.Fix32(x << 8),
|
||||
Y: raster.Fix32(y << 8),
|
||||
}
|
||||
}
|
||||
|
||||
// Hinting is the policy for snapping a glyph's contours to pixel boundaries.
|
||||
type Hinting int32
|
||||
|
||||
const (
|
||||
// NoHinting means to not perform any hinting.
|
||||
NoHinting = Hinting(truetype.NoHinting)
|
||||
// FullHinting means to use the font's hinting instructions.
|
||||
FullHinting = Hinting(truetype.FullHinting)
|
||||
)
|
||||
|
||||
// A Context holds the state for drawing text in a given font and size.
|
||||
type Context struct {
|
||||
r *raster.Rasterizer
|
||||
font *truetype.Font
|
||||
glyphBuf *truetype.GlyphBuf
|
||||
// clip is the clip rectangle for drawing.
|
||||
clip image.Rectangle
|
||||
// dst and src are the destination and source images for drawing.
|
||||
dst draw.Image
|
||||
src image.Image
|
||||
// fontSize and dpi are used to calculate scale. scale is the number of
|
||||
// 26.6 fixed point units in 1 em. hinting is the hinting policy.
|
||||
fontSize, dpi float64
|
||||
scale int32
|
||||
hinting Hinting
|
||||
// cache is the glyph cache.
|
||||
cache [nGlyphs * nXFractions * nYFractions]cacheEntry
|
||||
}
|
||||
|
||||
// PointToFix32 converts the given number of points (as in ``a 12 point font'')
|
||||
// into fixed point units.
|
||||
func (c *Context) PointToFix32(x float64) raster.Fix32 {
|
||||
return raster.Fix32(x * float64(c.dpi) * (256.0 / 72.0))
|
||||
}
|
||||
|
||||
// drawContour draws the given closed contour with the given offset.
|
||||
func (c *Context) drawContour(ps []truetype.Point, dx, dy raster.Fix32) {
|
||||
if len(ps) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// The low bit of each point's Flags value is whether the point is on the
|
||||
// curve. Truetype fonts only have quadratic Bézier curves, not cubics.
|
||||
// Thus, two consecutive off-curve points imply an on-curve point in the
|
||||
// middle of those two.
|
||||
//
|
||||
// See http://chanae.walon.org/pub/ttf/ttf_glyphs.htm for more details.
|
||||
|
||||
// ps[0] is a truetype.Point measured in FUnits and positive Y going
|
||||
// upwards. start is the same thing measured in fixed point units and
|
||||
// positive Y going downwards, and offset by (dx, dy).
|
||||
start := raster.Point{
|
||||
X: dx + raster.Fix32(ps[0].X<<2),
|
||||
Y: dy - raster.Fix32(ps[0].Y<<2),
|
||||
}
|
||||
others := []truetype.Point(nil)
|
||||
if ps[0].Flags&0x01 != 0 {
|
||||
others = ps[1:]
|
||||
} else {
|
||||
last := raster.Point{
|
||||
X: dx + raster.Fix32(ps[len(ps)-1].X<<2),
|
||||
Y: dy - raster.Fix32(ps[len(ps)-1].Y<<2),
|
||||
}
|
||||
if ps[len(ps)-1].Flags&0x01 != 0 {
|
||||
start = last
|
||||
others = ps[:len(ps)-1]
|
||||
} else {
|
||||
start = raster.Point{
|
||||
X: (start.X + last.X) / 2,
|
||||
Y: (start.Y + last.Y) / 2,
|
||||
}
|
||||
others = ps
|
||||
}
|
||||
}
|
||||
c.r.Start(start)
|
||||
q0, on0 := start, true
|
||||
for _, p := range others {
|
||||
q := raster.Point{
|
||||
X: dx + raster.Fix32(p.X<<2),
|
||||
Y: dy - raster.Fix32(p.Y<<2),
|
||||
}
|
||||
on := p.Flags&0x01 != 0
|
||||
if on {
|
||||
if on0 {
|
||||
c.r.Add1(q)
|
||||
} else {
|
||||
c.r.Add2(q0, q)
|
||||
}
|
||||
} else {
|
||||
if on0 {
|
||||
// No-op.
|
||||
} else {
|
||||
mid := raster.Point{
|
||||
X: (q0.X + q.X) / 2,
|
||||
Y: (q0.Y + q.Y) / 2,
|
||||
}
|
||||
c.r.Add2(q0, mid)
|
||||
}
|
||||
}
|
||||
q0, on0 = q, on
|
||||
}
|
||||
// Close the curve.
|
||||
if on0 {
|
||||
c.r.Add1(start)
|
||||
} else {
|
||||
c.r.Add2(q0, start)
|
||||
}
|
||||
}
|
||||
|
||||
// rasterize returns the advance width, glyph mask and integer-pixel offset
|
||||
// to render the given glyph at the given sub-pixel offsets.
|
||||
// The 24.8 fixed point arguments fx and fy must be in the range [0, 1).
|
||||
func (c *Context) rasterize(glyph truetype.Index, fx, fy raster.Fix32) (
|
||||
raster.Fix32, *image.Alpha, image.Point, error) {
|
||||
|
||||
if err := c.glyphBuf.Load(c.font, c.scale, glyph, truetype.Hinting(c.hinting)); err != nil {
|
||||
return 0, nil, image.Point{}, err
|
||||
}
|
||||
// Calculate the integer-pixel bounds for the glyph.
|
||||
xmin := int(fx+raster.Fix32(c.glyphBuf.B.XMin<<2)) >> 8
|
||||
ymin := int(fy-raster.Fix32(c.glyphBuf.B.YMax<<2)) >> 8
|
||||
xmax := int(fx+raster.Fix32(c.glyphBuf.B.XMax<<2)+0xff) >> 8
|
||||
ymax := int(fy-raster.Fix32(c.glyphBuf.B.YMin<<2)+0xff) >> 8
|
||||
if xmin > xmax || ymin > ymax {
|
||||
return 0, nil, image.Point{}, errors.New("freetype: negative sized glyph")
|
||||
}
|
||||
// A TrueType's glyph's nodes can have negative co-ordinates, but the
|
||||
// rasterizer clips anything left of x=0 or above y=0. xmin and ymin
|
||||
// are the pixel offsets, based on the font's FUnit metrics, that let
|
||||
// a negative co-ordinate in TrueType space be non-negative in
|
||||
// rasterizer space. xmin and ymin are typically <= 0.
|
||||
fx += raster.Fix32(-xmin << 8)
|
||||
fy += raster.Fix32(-ymin << 8)
|
||||
// Rasterize the glyph's vectors.
|
||||
c.r.Clear()
|
||||
e0 := 0
|
||||
for _, e1 := range c.glyphBuf.End {
|
||||
c.drawContour(c.glyphBuf.Point[e0:e1], fx, fy)
|
||||
e0 = e1
|
||||
}
|
||||
a := image.NewAlpha(image.Rect(0, 0, xmax-xmin, ymax-ymin))
|
||||
c.r.Rasterize(raster.NewAlphaSrcPainter(a))
|
||||
return raster.Fix32(c.glyphBuf.AdvanceWidth << 2), a, image.Point{xmin, ymin}, nil
|
||||
}
|
||||
|
||||
// glyph returns the advance width, glyph mask and integer-pixel offset to
|
||||
// render the given glyph at the given sub-pixel point. It is a cache for the
|
||||
// rasterize method. Unlike rasterize, p's co-ordinates do not have to be in
|
||||
// the range [0, 1).
|
||||
func (c *Context) glyph(glyph truetype.Index, p raster.Point) (
|
||||
raster.Fix32, *image.Alpha, image.Point, error) {
|
||||
|
||||
// Split p.X and p.Y into their integer and fractional parts.
|
||||
ix, fx := int(p.X>>8), p.X&0xff
|
||||
iy, fy := int(p.Y>>8), p.Y&0xff
|
||||
// Calculate the index t into the cache array.
|
||||
tg := int(glyph) % nGlyphs
|
||||
tx := int(fx) / (256 / nXFractions)
|
||||
ty := int(fy) / (256 / nYFractions)
|
||||
t := ((tg*nXFractions)+tx)*nYFractions + ty
|
||||
// Check for a cache hit.
|
||||
if e := c.cache[t]; e.valid && e.glyph == glyph {
|
||||
return e.advanceWidth, e.mask, e.offset.Add(image.Point{ix, iy}), nil
|
||||
}
|
||||
// Rasterize the glyph and put the result into the cache.
|
||||
advanceWidth, mask, offset, err := c.rasterize(glyph, fx, fy)
|
||||
if err != nil {
|
||||
return 0, nil, image.Point{}, err
|
||||
}
|
||||
c.cache[t] = cacheEntry{true, glyph, advanceWidth, mask, offset}
|
||||
return advanceWidth, mask, offset.Add(image.Point{ix, iy}), nil
|
||||
}
|
||||
|
||||
// DrawString draws s at p and returns p advanced by the text extent. The text
|
||||
// is placed so that the left edge of the em square of the first character of s
|
||||
// and the baseline intersect at p. The majority of the affected pixels will be
|
||||
// above and to the right of the point, but some may be below or to the left.
|
||||
// For example, drawing a string that starts with a 'J' in an italic font may
|
||||
// affect pixels below and left of the point.
|
||||
// p is a raster.Point and can therefore represent sub-pixel positions.
|
||||
func (c *Context) DrawString(s string, p raster.Point) (raster.Point, error) {
|
||||
if c.font == nil {
|
||||
return raster.Point{}, errors.New("freetype: DrawText called with a nil font")
|
||||
}
|
||||
prev, hasPrev := truetype.Index(0), false
|
||||
for _, rune := range s {
|
||||
index := c.font.Index(rune)
|
||||
if hasPrev {
|
||||
kern := raster.Fix32(c.font.Kerning(c.scale, prev, index)) << 2
|
||||
if c.hinting != NoHinting {
|
||||
kern = (kern + 128) &^ 255
|
||||
}
|
||||
p.X += kern
|
||||
}
|
||||
advanceWidth, mask, offset, err := c.glyph(index, p)
|
||||
if err != nil {
|
||||
return raster.Point{}, err
|
||||
}
|
||||
p.X += advanceWidth
|
||||
glyphRect := mask.Bounds().Add(offset)
|
||||
dr := c.clip.Intersect(glyphRect)
|
||||
if !dr.Empty() {
|
||||
mp := image.Point{0, dr.Min.Y - glyphRect.Min.Y}
|
||||
draw.DrawMask(c.dst, dr, c.src, image.ZP, mask, mp, draw.Over)
|
||||
}
|
||||
prev, hasPrev = index, true
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// recalc recalculates scale and bounds values from the font size, screen
|
||||
// resolution and font metrics, and invalidates the glyph cache.
|
||||
func (c *Context) recalc() {
|
||||
c.scale = int32(c.fontSize * c.dpi * (64.0 / 72.0))
|
||||
if c.font == nil {
|
||||
c.r.SetBounds(0, 0)
|
||||
} else {
|
||||
// Set the rasterizer's bounds to be big enough to handle the largest glyph.
|
||||
b := c.font.Bounds(c.scale)
|
||||
xmin := +int(b.XMin) >> 6
|
||||
ymin := -int(b.YMax) >> 6
|
||||
xmax := +int(b.XMax+63) >> 6
|
||||
ymax := -int(b.YMin-63) >> 6
|
||||
c.r.SetBounds(xmax-xmin, ymax-ymin)
|
||||
}
|
||||
for i := range c.cache {
|
||||
c.cache[i] = cacheEntry{}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDPI sets the screen resolution in dots per inch.
|
||||
func (c *Context) SetDPI(dpi float64) {
|
||||
if c.dpi == dpi {
|
||||
return
|
||||
}
|
||||
c.dpi = dpi
|
||||
c.recalc()
|
||||
}
|
||||
|
||||
// SetFont sets the font used to draw text.
|
||||
func (c *Context) SetFont(font *truetype.Font) {
|
||||
if c.font == font {
|
||||
return
|
||||
}
|
||||
c.font = font
|
||||
c.recalc()
|
||||
}
|
||||
|
||||
// SetFontSize sets the font size in points (as in ``a 12 point font'').
|
||||
func (c *Context) SetFontSize(fontSize float64) {
|
||||
if c.fontSize == fontSize {
|
||||
return
|
||||
}
|
||||
c.fontSize = fontSize
|
||||
c.recalc()
|
||||
}
|
||||
|
||||
// SetHinting sets the hinting policy.
|
||||
func (c *Context) SetHinting(hinting Hinting) {
|
||||
c.hinting = hinting
|
||||
for i := range c.cache {
|
||||
c.cache[i] = cacheEntry{}
|
||||
}
|
||||
}
|
||||
|
||||
// SetDst sets the destination image for draw operations.
|
||||
func (c *Context) SetDst(dst draw.Image) {
|
||||
c.dst = dst
|
||||
}
|
||||
|
||||
// SetSrc sets the source image for draw operations. This is typically an
|
||||
// image.Uniform.
|
||||
func (c *Context) SetSrc(src image.Image) {
|
||||
c.src = src
|
||||
}
|
||||
|
||||
// SetClip sets the clip rectangle for drawing.
|
||||
func (c *Context) SetClip(clip image.Rectangle) {
|
||||
c.clip = clip
|
||||
}
|
||||
|
||||
// TODO(nigeltao): implement Context.SetGamma.
|
||||
|
||||
// NewContext creates a new Context.
|
||||
func NewContext() *Context {
|
||||
return &Context{
|
||||
r: raster.NewRasterizer(0, 0),
|
||||
glyphBuf: truetype.NewGlyphBuf(),
|
||||
fontSize: 12,
|
||||
dpi: 72,
|
||||
scale: 12 << 6,
|
||||
}
|
||||
}
|
||||
59
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/freetype_test.go
сгенерированный
поставляемый
59
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/freetype_test.go
сгенерированный
поставляемый
@@ -1,59 +0,0 @@
|
||||
// Copyright 2012 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package freetype
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func BenchmarkDrawString(b *testing.B) {
|
||||
data, err := ioutil.ReadFile("../licenses/gpl.txt")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
lines := strings.Split(string(data), "\n")
|
||||
|
||||
data, err = ioutil.ReadFile("../testdata/luxisr.ttf")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
font, err := ParseFont(data)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
dst := image.NewRGBA(image.Rect(0, 0, 800, 600))
|
||||
draw.Draw(dst, dst.Bounds(), image.White, image.ZP, draw.Src)
|
||||
|
||||
c := NewContext()
|
||||
c.SetDst(dst)
|
||||
c.SetClip(dst.Bounds())
|
||||
c.SetSrc(image.Black)
|
||||
c.SetFont(font)
|
||||
|
||||
var ms runtime.MemStats
|
||||
runtime.ReadMemStats(&ms)
|
||||
mallocs := ms.Mallocs
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
for j, line := range lines {
|
||||
_, err := c.DrawString(line, Pt(0, (j*16)%600))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
b.StopTimer()
|
||||
runtime.ReadMemStats(&ms)
|
||||
mallocs = ms.Mallocs - mallocs
|
||||
b.Logf("%d iterations, %d mallocs per iteration\n", b.N, int(mallocs)/b.N)
|
||||
}
|
||||
280
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/geom.go
сгенерированный
поставляемый
280
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/geom.go
сгенерированный
поставляемый
@@ -1,280 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package raster
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// A Fix32 is a 24.8 fixed point number.
|
||||
type Fix32 int32
|
||||
|
||||
// A Fix64 is a 48.16 fixed point number.
|
||||
type Fix64 int64
|
||||
|
||||
// String returns a human-readable representation of a 24.8 fixed point number.
|
||||
// For example, the number one-and-a-quarter becomes "1:064".
|
||||
func (x Fix32) String() string {
|
||||
if x < 0 {
|
||||
x = -x
|
||||
return fmt.Sprintf("-%d:%03d", int32(x/256), int32(x%256))
|
||||
}
|
||||
return fmt.Sprintf("%d:%03d", int32(x/256), int32(x%256))
|
||||
}
|
||||
|
||||
// String returns a human-readable representation of a 48.16 fixed point number.
|
||||
// For example, the number one-and-a-quarter becomes "1:16384".
|
||||
func (x Fix64) String() string {
|
||||
if x < 0 {
|
||||
x = -x
|
||||
return fmt.Sprintf("-%d:%05d", int64(x/65536), int64(x%65536))
|
||||
}
|
||||
return fmt.Sprintf("%d:%05d", int64(x/65536), int64(x%65536))
|
||||
}
|
||||
|
||||
// maxAbs returns the maximum of abs(a) and abs(b).
|
||||
func maxAbs(a, b Fix32) Fix32 {
|
||||
if a < 0 {
|
||||
a = -a
|
||||
}
|
||||
if b < 0 {
|
||||
b = -b
|
||||
}
|
||||
if a < b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// A Point represents a two-dimensional point or vector, in 24.8 fixed point
|
||||
// format.
|
||||
type Point struct {
|
||||
X, Y Fix32
|
||||
}
|
||||
|
||||
// String returns a human-readable representation of a Point.
|
||||
func (p Point) String() string {
|
||||
return "(" + p.X.String() + ", " + p.Y.String() + ")"
|
||||
}
|
||||
|
||||
// Add returns the vector p + q.
|
||||
func (p Point) Add(q Point) Point {
|
||||
return Point{p.X + q.X, p.Y + q.Y}
|
||||
}
|
||||
|
||||
// Sub returns the vector p - q.
|
||||
func (p Point) Sub(q Point) Point {
|
||||
return Point{p.X - q.X, p.Y - q.Y}
|
||||
}
|
||||
|
||||
// Mul returns the vector k * p.
|
||||
func (p Point) Mul(k Fix32) Point {
|
||||
return Point{p.X * k / 256, p.Y * k / 256}
|
||||
}
|
||||
|
||||
// Neg returns the vector -p, or equivalently p rotated by 180 degrees.
|
||||
func (p Point) Neg() Point {
|
||||
return Point{-p.X, -p.Y}
|
||||
}
|
||||
|
||||
// Dot returns the dot product p·q.
|
||||
func (p Point) Dot(q Point) Fix64 {
|
||||
px, py := int64(p.X), int64(p.Y)
|
||||
qx, qy := int64(q.X), int64(q.Y)
|
||||
return Fix64(px*qx + py*qy)
|
||||
}
|
||||
|
||||
// Len returns the length of the vector p.
|
||||
func (p Point) Len() Fix32 {
|
||||
// TODO(nigeltao): use fixed point math.
|
||||
x := float64(p.X)
|
||||
y := float64(p.Y)
|
||||
return Fix32(math.Sqrt(x*x + y*y))
|
||||
}
|
||||
|
||||
// Norm returns the vector p normalized to the given length, or the zero Point
|
||||
// if p is degenerate.
|
||||
func (p Point) Norm(length Fix32) Point {
|
||||
d := p.Len()
|
||||
if d == 0 {
|
||||
return Point{}
|
||||
}
|
||||
s, t := int64(length), int64(d)
|
||||
x := int64(p.X) * s / t
|
||||
y := int64(p.Y) * s / t
|
||||
return Point{Fix32(x), Fix32(y)}
|
||||
}
|
||||
|
||||
// Rot45CW returns the vector p rotated clockwise by 45 degrees.
|
||||
// Note that the Y-axis grows downwards, so {1, 0}.Rot45CW is {1/√2, 1/√2}.
|
||||
func (p Point) Rot45CW() Point {
|
||||
// 181/256 is approximately 1/√2, or sin(π/4).
|
||||
px, py := int64(p.X), int64(p.Y)
|
||||
qx := (+px - py) * 181 / 256
|
||||
qy := (+px + py) * 181 / 256
|
||||
return Point{Fix32(qx), Fix32(qy)}
|
||||
}
|
||||
|
||||
// Rot90CW returns the vector p rotated clockwise by 90 degrees.
|
||||
// Note that the Y-axis grows downwards, so {1, 0}.Rot90CW is {0, 1}.
|
||||
func (p Point) Rot90CW() Point {
|
||||
return Point{-p.Y, p.X}
|
||||
}
|
||||
|
||||
// Rot135CW returns the vector p rotated clockwise by 135 degrees.
|
||||
// Note that the Y-axis grows downwards, so {1, 0}.Rot135CW is {-1/√2, 1/√2}.
|
||||
func (p Point) Rot135CW() Point {
|
||||
// 181/256 is approximately 1/√2, or sin(π/4).
|
||||
px, py := int64(p.X), int64(p.Y)
|
||||
qx := (-px - py) * 181 / 256
|
||||
qy := (+px - py) * 181 / 256
|
||||
return Point{Fix32(qx), Fix32(qy)}
|
||||
}
|
||||
|
||||
// Rot45CCW returns the vector p rotated counter-clockwise by 45 degrees.
|
||||
// Note that the Y-axis grows downwards, so {1, 0}.Rot45CCW is {1/√2, -1/√2}.
|
||||
func (p Point) Rot45CCW() Point {
|
||||
// 181/256 is approximately 1/√2, or sin(π/4).
|
||||
px, py := int64(p.X), int64(p.Y)
|
||||
qx := (+px + py) * 181 / 256
|
||||
qy := (-px + py) * 181 / 256
|
||||
return Point{Fix32(qx), Fix32(qy)}
|
||||
}
|
||||
|
||||
// Rot90CCW returns the vector p rotated counter-clockwise by 90 degrees.
|
||||
// Note that the Y-axis grows downwards, so {1, 0}.Rot90CCW is {0, -1}.
|
||||
func (p Point) Rot90CCW() Point {
|
||||
return Point{p.Y, -p.X}
|
||||
}
|
||||
|
||||
// Rot135CCW returns the vector p rotated counter-clockwise by 135 degrees.
|
||||
// Note that the Y-axis grows downwards, so {1, 0}.Rot135CCW is {-1/√2, -1/√2}.
|
||||
func (p Point) Rot135CCW() Point {
|
||||
// 181/256 is approximately 1/√2, or sin(π/4).
|
||||
px, py := int64(p.X), int64(p.Y)
|
||||
qx := (-px + py) * 181 / 256
|
||||
qy := (-px - py) * 181 / 256
|
||||
return Point{Fix32(qx), Fix32(qy)}
|
||||
}
|
||||
|
||||
// An Adder accumulates points on a curve.
|
||||
type Adder interface {
|
||||
// Start starts a new curve at the given point.
|
||||
Start(a Point)
|
||||
// Add1 adds a linear segment to the current curve.
|
||||
Add1(b Point)
|
||||
// Add2 adds a quadratic segment to the current curve.
|
||||
Add2(b, c Point)
|
||||
// Add3 adds a cubic segment to the current curve.
|
||||
Add3(b, c, d Point)
|
||||
}
|
||||
|
||||
// A Path is a sequence of curves, and a curve is a start point followed by a
|
||||
// sequence of linear, quadratic or cubic segments.
|
||||
type Path []Fix32
|
||||
|
||||
// String returns a human-readable representation of a Path.
|
||||
func (p Path) String() string {
|
||||
s := ""
|
||||
for i := 0; i < len(p); {
|
||||
if i != 0 {
|
||||
s += " "
|
||||
}
|
||||
switch p[i] {
|
||||
case 0:
|
||||
s += "S0" + fmt.Sprint([]Fix32(p[i+1:i+3]))
|
||||
i += 4
|
||||
case 1:
|
||||
s += "A1" + fmt.Sprint([]Fix32(p[i+1:i+3]))
|
||||
i += 4
|
||||
case 2:
|
||||
s += "A2" + fmt.Sprint([]Fix32(p[i+1:i+5]))
|
||||
i += 6
|
||||
case 3:
|
||||
s += "A3" + fmt.Sprint([]Fix32(p[i+1:i+7]))
|
||||
i += 8
|
||||
default:
|
||||
panic("freetype/raster: bad path")
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Clear cancels any previous calls to p.Start or p.AddXxx.
|
||||
func (p *Path) Clear() {
|
||||
*p = (*p)[:0]
|
||||
}
|
||||
|
||||
// Start starts a new curve at the given point.
|
||||
func (p *Path) Start(a Point) {
|
||||
*p = append(*p, 0, a.X, a.Y, 0)
|
||||
}
|
||||
|
||||
// Add1 adds a linear segment to the current curve.
|
||||
func (p *Path) Add1(b Point) {
|
||||
*p = append(*p, 1, b.X, b.Y, 1)
|
||||
}
|
||||
|
||||
// Add2 adds a quadratic segment to the current curve.
|
||||
func (p *Path) Add2(b, c Point) {
|
||||
*p = append(*p, 2, b.X, b.Y, c.X, c.Y, 2)
|
||||
}
|
||||
|
||||
// Add3 adds a cubic segment to the current curve.
|
||||
func (p *Path) Add3(b, c, d Point) {
|
||||
*p = append(*p, 3, b.X, b.Y, c.X, c.Y, d.X, d.Y, 3)
|
||||
}
|
||||
|
||||
// AddPath adds the Path q to p.
|
||||
func (p *Path) AddPath(q Path) {
|
||||
*p = append(*p, q...)
|
||||
}
|
||||
|
||||
// AddStroke adds a stroked Path.
|
||||
func (p *Path) AddStroke(q Path, width Fix32, cr Capper, jr Joiner) {
|
||||
Stroke(p, q, width, cr, jr)
|
||||
}
|
||||
|
||||
// firstPoint returns the first point in a non-empty Path.
|
||||
func (p Path) firstPoint() Point {
|
||||
return Point{p[1], p[2]}
|
||||
}
|
||||
|
||||
// lastPoint returns the last point in a non-empty Path.
|
||||
func (p Path) lastPoint() Point {
|
||||
return Point{p[len(p)-3], p[len(p)-2]}
|
||||
}
|
||||
|
||||
// addPathReversed adds q reversed to p.
|
||||
// For example, if q consists of a linear segment from A to B followed by a
|
||||
// quadratic segment from B to C to D, then the values of q looks like:
|
||||
// index: 01234567890123
|
||||
// value: 0AA01BB12CCDD2
|
||||
// So, when adding q backwards to p, we want to Add2(C, B) followed by Add1(A).
|
||||
func addPathReversed(p Adder, q Path) {
|
||||
if len(q) == 0 {
|
||||
return
|
||||
}
|
||||
i := len(q) - 1
|
||||
for {
|
||||
switch q[i] {
|
||||
case 0:
|
||||
return
|
||||
case 1:
|
||||
i -= 4
|
||||
p.Add1(Point{q[i-2], q[i-1]})
|
||||
case 2:
|
||||
i -= 6
|
||||
p.Add2(Point{q[i+2], q[i+3]}, Point{q[i-2], q[i-1]})
|
||||
case 3:
|
||||
i -= 8
|
||||
p.Add3(Point{q[i+4], q[i+5]}, Point{q[i+2], q[i+3]}, Point{q[i-2], q[i-1]})
|
||||
default:
|
||||
panic("freetype/raster: bad path")
|
||||
}
|
||||
}
|
||||
}
|
||||
292
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/paint.go
сгенерированный
поставляемый
292
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/paint.go
сгенерированный
поставляемый
@@ -1,292 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package raster
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"math"
|
||||
)
|
||||
|
||||
// A Span is a horizontal segment of pixels with constant alpha. X0 is an
|
||||
// inclusive bound and X1 is exclusive, the same as for slices. A fully
|
||||
// opaque Span has A == 1<<32 - 1.
|
||||
type Span struct {
|
||||
Y, X0, X1 int
|
||||
A uint32
|
||||
}
|
||||
|
||||
// A Painter knows how to paint a batch of Spans. Rasterization may involve
|
||||
// Painting multiple batches, and done will be true for the final batch.
|
||||
// The Spans' Y values are monotonically increasing during a rasterization.
|
||||
// Paint may use all of ss as scratch space during the call.
|
||||
type Painter interface {
|
||||
Paint(ss []Span, done bool)
|
||||
}
|
||||
|
||||
// The PainterFunc type adapts an ordinary function to the Painter interface.
|
||||
type PainterFunc func(ss []Span, done bool)
|
||||
|
||||
// Paint just delegates the call to f.
|
||||
func (f PainterFunc) Paint(ss []Span, done bool) { f(ss, done) }
|
||||
|
||||
// An AlphaOverPainter is a Painter that paints Spans onto an image.Alpha
|
||||
// using the Over Porter-Duff composition operator.
|
||||
type AlphaOverPainter struct {
|
||||
Image *image.Alpha
|
||||
}
|
||||
|
||||
// Paint satisfies the Painter interface by painting ss onto an image.Alpha.
|
||||
func (r AlphaOverPainter) Paint(ss []Span, done bool) {
|
||||
b := r.Image.Bounds()
|
||||
for _, s := range ss {
|
||||
if s.Y < b.Min.Y {
|
||||
continue
|
||||
}
|
||||
if s.Y >= b.Max.Y {
|
||||
return
|
||||
}
|
||||
if s.X0 < b.Min.X {
|
||||
s.X0 = b.Min.X
|
||||
}
|
||||
if s.X1 > b.Max.X {
|
||||
s.X1 = b.Max.X
|
||||
}
|
||||
if s.X0 >= s.X1 {
|
||||
continue
|
||||
}
|
||||
base := (s.Y-r.Image.Rect.Min.Y)*r.Image.Stride - r.Image.Rect.Min.X
|
||||
p := r.Image.Pix[base+s.X0 : base+s.X1]
|
||||
a := int(s.A >> 24)
|
||||
for i, c := range p {
|
||||
v := int(c)
|
||||
p[i] = uint8((v*255 + (255-v)*a) / 255)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewAlphaOverPainter creates a new AlphaOverPainter for the given image.
|
||||
func NewAlphaOverPainter(m *image.Alpha) AlphaOverPainter {
|
||||
return AlphaOverPainter{m}
|
||||
}
|
||||
|
||||
// An AlphaSrcPainter is a Painter that paints Spans onto an image.Alpha
|
||||
// using the Src Porter-Duff composition operator.
|
||||
type AlphaSrcPainter struct {
|
||||
Image *image.Alpha
|
||||
}
|
||||
|
||||
// Paint satisfies the Painter interface by painting ss onto an image.Alpha.
|
||||
func (r AlphaSrcPainter) Paint(ss []Span, done bool) {
|
||||
b := r.Image.Bounds()
|
||||
for _, s := range ss {
|
||||
if s.Y < b.Min.Y {
|
||||
continue
|
||||
}
|
||||
if s.Y >= b.Max.Y {
|
||||
return
|
||||
}
|
||||
if s.X0 < b.Min.X {
|
||||
s.X0 = b.Min.X
|
||||
}
|
||||
if s.X1 > b.Max.X {
|
||||
s.X1 = b.Max.X
|
||||
}
|
||||
if s.X0 >= s.X1 {
|
||||
continue
|
||||
}
|
||||
base := (s.Y-r.Image.Rect.Min.Y)*r.Image.Stride - r.Image.Rect.Min.X
|
||||
p := r.Image.Pix[base+s.X0 : base+s.X1]
|
||||
color := uint8(s.A >> 24)
|
||||
for i := range p {
|
||||
p[i] = color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewAlphaSrcPainter creates a new AlphaSrcPainter for the given image.
|
||||
func NewAlphaSrcPainter(m *image.Alpha) AlphaSrcPainter {
|
||||
return AlphaSrcPainter{m}
|
||||
}
|
||||
|
||||
type RGBAPainter struct {
|
||||
// The image to compose onto.
|
||||
Image *image.RGBA
|
||||
// The Porter-Duff composition operator.
|
||||
Op draw.Op
|
||||
// The 16-bit color to paint the spans.
|
||||
cr, cg, cb, ca uint32
|
||||
}
|
||||
|
||||
// Paint satisfies the Painter interface by painting ss onto an image.RGBA.
|
||||
func (r *RGBAPainter) Paint(ss []Span, done bool) {
|
||||
b := r.Image.Bounds()
|
||||
for _, s := range ss {
|
||||
if s.Y < b.Min.Y {
|
||||
continue
|
||||
}
|
||||
if s.Y >= b.Max.Y {
|
||||
return
|
||||
}
|
||||
if s.X0 < b.Min.X {
|
||||
s.X0 = b.Min.X
|
||||
}
|
||||
if s.X1 > b.Max.X {
|
||||
s.X1 = b.Max.X
|
||||
}
|
||||
if s.X0 >= s.X1 {
|
||||
continue
|
||||
}
|
||||
// This code is similar to drawGlyphOver in $GOROOT/src/pkg/image/draw/draw.go.
|
||||
ma := s.A >> 16
|
||||
const m = 1<<16 - 1
|
||||
i0 := (s.Y-r.Image.Rect.Min.Y)*r.Image.Stride + (s.X0-r.Image.Rect.Min.X)*4
|
||||
i1 := i0 + (s.X1-s.X0)*4
|
||||
if r.Op == draw.Over {
|
||||
for i := i0; i < i1; i += 4 {
|
||||
dr := uint32(r.Image.Pix[i+0])
|
||||
dg := uint32(r.Image.Pix[i+1])
|
||||
db := uint32(r.Image.Pix[i+2])
|
||||
da := uint32(r.Image.Pix[i+3])
|
||||
a := (m - (r.ca * ma / m)) * 0x101
|
||||
r.Image.Pix[i+0] = uint8((dr*a + r.cr*ma) / m >> 8)
|
||||
r.Image.Pix[i+1] = uint8((dg*a + r.cg*ma) / m >> 8)
|
||||
r.Image.Pix[i+2] = uint8((db*a + r.cb*ma) / m >> 8)
|
||||
r.Image.Pix[i+3] = uint8((da*a + r.ca*ma) / m >> 8)
|
||||
}
|
||||
} else {
|
||||
for i := i0; i < i1; i += 4 {
|
||||
r.Image.Pix[i+0] = uint8(r.cr * ma / m >> 8)
|
||||
r.Image.Pix[i+1] = uint8(r.cg * ma / m >> 8)
|
||||
r.Image.Pix[i+2] = uint8(r.cb * ma / m >> 8)
|
||||
r.Image.Pix[i+3] = uint8(r.ca * ma / m >> 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetColor sets the color to paint the spans.
|
||||
func (r *RGBAPainter) SetColor(c color.Color) {
|
||||
r.cr, r.cg, r.cb, r.ca = c.RGBA()
|
||||
}
|
||||
|
||||
// NewRGBAPainter creates a new RGBAPainter for the given image.
|
||||
func NewRGBAPainter(m *image.RGBA) *RGBAPainter {
|
||||
return &RGBAPainter{Image: m}
|
||||
}
|
||||
|
||||
// A MonochromePainter wraps another Painter, quantizing each Span's alpha to
|
||||
// be either fully opaque or fully transparent.
|
||||
type MonochromePainter struct {
|
||||
Painter Painter
|
||||
y, x0, x1 int
|
||||
}
|
||||
|
||||
// Paint delegates to the wrapped Painter after quantizing each Span's alpha
|
||||
// value and merging adjacent fully opaque Spans.
|
||||
func (m *MonochromePainter) Paint(ss []Span, done bool) {
|
||||
// We compact the ss slice, discarding any Spans whose alpha quantizes to zero.
|
||||
j := 0
|
||||
for _, s := range ss {
|
||||
if s.A >= 1<<31 {
|
||||
if m.y == s.Y && m.x1 == s.X0 {
|
||||
m.x1 = s.X1
|
||||
} else {
|
||||
ss[j] = Span{m.y, m.x0, m.x1, 1<<32 - 1}
|
||||
j++
|
||||
m.y, m.x0, m.x1 = s.Y, s.X0, s.X1
|
||||
}
|
||||
}
|
||||
}
|
||||
if done {
|
||||
// Flush the accumulated Span.
|
||||
finalSpan := Span{m.y, m.x0, m.x1, 1<<32 - 1}
|
||||
if j < len(ss) {
|
||||
ss[j] = finalSpan
|
||||
j++
|
||||
m.Painter.Paint(ss[:j], true)
|
||||
} else if j == len(ss) {
|
||||
m.Painter.Paint(ss, false)
|
||||
if cap(ss) > 0 {
|
||||
ss = ss[:1]
|
||||
} else {
|
||||
ss = make([]Span, 1)
|
||||
}
|
||||
ss[0] = finalSpan
|
||||
m.Painter.Paint(ss, true)
|
||||
} else {
|
||||
panic("unreachable")
|
||||
}
|
||||
// Reset the accumulator, so that this Painter can be re-used.
|
||||
m.y, m.x0, m.x1 = 0, 0, 0
|
||||
} else {
|
||||
m.Painter.Paint(ss[:j], false)
|
||||
}
|
||||
}
|
||||
|
||||
// NewMonochromePainter creates a new MonochromePainter that wraps the given
|
||||
// Painter.
|
||||
func NewMonochromePainter(p Painter) *MonochromePainter {
|
||||
return &MonochromePainter{Painter: p}
|
||||
}
|
||||
|
||||
// A GammaCorrectionPainter wraps another Painter, performing gamma-correction
|
||||
// on each Span's alpha value.
|
||||
type GammaCorrectionPainter struct {
|
||||
// The wrapped Painter.
|
||||
Painter Painter
|
||||
// Precomputed alpha values for linear interpolation, with fully opaque == 1<<16-1.
|
||||
a [256]uint16
|
||||
// Whether gamma correction is a no-op.
|
||||
gammaIsOne bool
|
||||
}
|
||||
|
||||
// Paint delegates to the wrapped Painter after performing gamma-correction
|
||||
// on each Span.
|
||||
func (g *GammaCorrectionPainter) Paint(ss []Span, done bool) {
|
||||
if !g.gammaIsOne {
|
||||
const (
|
||||
M = 0x1010101 // 255*M == 1<<32-1
|
||||
N = 0x8080 // N = M>>9, and N < 1<<16-1
|
||||
)
|
||||
for i, s := range ss {
|
||||
if s.A == 0 || s.A == 1<<32-1 {
|
||||
continue
|
||||
}
|
||||
p, q := s.A/M, (s.A%M)>>9
|
||||
// The resultant alpha is a linear interpolation of g.a[p] and g.a[p+1].
|
||||
a := uint32(g.a[p])*(N-q) + uint32(g.a[p+1])*q
|
||||
a = (a + N/2) / N
|
||||
// Convert the alpha from 16-bit (which is g.a's range) to 32-bit.
|
||||
a |= a << 16
|
||||
ss[i].A = a
|
||||
}
|
||||
}
|
||||
g.Painter.Paint(ss, done)
|
||||
}
|
||||
|
||||
// SetGamma sets the gamma value.
|
||||
func (g *GammaCorrectionPainter) SetGamma(gamma float64) {
|
||||
if gamma == 1.0 {
|
||||
g.gammaIsOne = true
|
||||
return
|
||||
}
|
||||
g.gammaIsOne = false
|
||||
for i := 0; i < 256; i++ {
|
||||
a := float64(i) / 0xff
|
||||
a = math.Pow(a, gamma)
|
||||
g.a[i] = uint16(0xffff * a)
|
||||
}
|
||||
}
|
||||
|
||||
// NewGammaCorrectionPainter creates a new GammaCorrectionPainter that wraps
|
||||
// the given Painter.
|
||||
func NewGammaCorrectionPainter(p Painter, gamma float64) *GammaCorrectionPainter {
|
||||
g := &GammaCorrectionPainter{Painter: p}
|
||||
g.SetGamma(gamma)
|
||||
return g
|
||||
}
|
||||
579
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/raster.go
сгенерированный
поставляемый
579
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/raster.go
сгенерированный
поставляемый
@@ -1,579 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
// The raster package provides an anti-aliasing 2-D rasterizer.
|
||||
//
|
||||
// It is part of the larger Freetype-Go suite of font-related packages,
|
||||
// but the raster package is not specific to font rasterization, and can
|
||||
// be used standalone without any other Freetype-Go package.
|
||||
//
|
||||
// Rasterization is done by the same area/coverage accumulation algorithm
|
||||
// as the Freetype "smooth" module, and the Anti-Grain Geometry library.
|
||||
// A description of the area/coverage algorithm is at
|
||||
// http://projects.tuxee.net/cl-vectors/section-the-cl-aa-algorithm
|
||||
package raster
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// A cell is part of a linked list (for a given yi co-ordinate) of accumulated
|
||||
// area/coverage for the pixel at (xi, yi).
|
||||
type cell struct {
|
||||
xi int
|
||||
area, cover int
|
||||
next int
|
||||
}
|
||||
|
||||
type Rasterizer struct {
|
||||
// If false, the default behavior is to use the even-odd winding fill
|
||||
// rule during Rasterize.
|
||||
UseNonZeroWinding bool
|
||||
// An offset (in pixels) to the painted spans.
|
||||
Dx, Dy int
|
||||
|
||||
// The width of the Rasterizer. The height is implicit in len(cellIndex).
|
||||
width int
|
||||
// splitScaleN is the scaling factor used to determine how many times
|
||||
// to decompose a quadratic or cubic segment into a linear approximation.
|
||||
splitScale2, splitScale3 int
|
||||
|
||||
// The current pen position.
|
||||
a Point
|
||||
// The current cell and its area/coverage being accumulated.
|
||||
xi, yi int
|
||||
area, cover int
|
||||
|
||||
// Saved cells.
|
||||
cell []cell
|
||||
// Linked list of cells, one per row.
|
||||
cellIndex []int
|
||||
// Buffers.
|
||||
cellBuf [256]cell
|
||||
cellIndexBuf [64]int
|
||||
spanBuf [64]Span
|
||||
}
|
||||
|
||||
// findCell returns the index in r.cell for the cell corresponding to
|
||||
// (r.xi, r.yi). The cell is created if necessary.
|
||||
func (r *Rasterizer) findCell() int {
|
||||
if r.yi < 0 || r.yi >= len(r.cellIndex) {
|
||||
return -1
|
||||
}
|
||||
xi := r.xi
|
||||
if xi < 0 {
|
||||
xi = -1
|
||||
} else if xi > r.width {
|
||||
xi = r.width
|
||||
}
|
||||
i, prev := r.cellIndex[r.yi], -1
|
||||
for i != -1 && r.cell[i].xi <= xi {
|
||||
if r.cell[i].xi == xi {
|
||||
return i
|
||||
}
|
||||
i, prev = r.cell[i].next, i
|
||||
}
|
||||
c := len(r.cell)
|
||||
if c == cap(r.cell) {
|
||||
buf := make([]cell, c, 4*c)
|
||||
copy(buf, r.cell)
|
||||
r.cell = buf[0 : c+1]
|
||||
} else {
|
||||
r.cell = r.cell[0 : c+1]
|
||||
}
|
||||
r.cell[c] = cell{xi, 0, 0, i}
|
||||
if prev == -1 {
|
||||
r.cellIndex[r.yi] = c
|
||||
} else {
|
||||
r.cell[prev].next = c
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// saveCell saves any accumulated r.area/r.cover for (r.xi, r.yi).
|
||||
func (r *Rasterizer) saveCell() {
|
||||
if r.area != 0 || r.cover != 0 {
|
||||
i := r.findCell()
|
||||
if i != -1 {
|
||||
r.cell[i].area += r.area
|
||||
r.cell[i].cover += r.cover
|
||||
}
|
||||
r.area = 0
|
||||
r.cover = 0
|
||||
}
|
||||
}
|
||||
|
||||
// setCell sets the (xi, yi) cell that r is accumulating area/coverage for.
|
||||
func (r *Rasterizer) setCell(xi, yi int) {
|
||||
if r.xi != xi || r.yi != yi {
|
||||
r.saveCell()
|
||||
r.xi, r.yi = xi, yi
|
||||
}
|
||||
}
|
||||
|
||||
// scan accumulates area/coverage for the yi'th scanline, going from
|
||||
// x0 to x1 in the horizontal direction (in 24.8 fixed point co-ordinates)
|
||||
// and from y0f to y1f fractional vertical units within that scanline.
|
||||
func (r *Rasterizer) scan(yi int, x0, y0f, x1, y1f Fix32) {
|
||||
// Break the 24.8 fixed point X co-ordinates into integral and fractional parts.
|
||||
x0i := int(x0) / 256
|
||||
x0f := x0 - Fix32(256*x0i)
|
||||
x1i := int(x1) / 256
|
||||
x1f := x1 - Fix32(256*x1i)
|
||||
|
||||
// A perfectly horizontal scan.
|
||||
if y0f == y1f {
|
||||
r.setCell(x1i, yi)
|
||||
return
|
||||
}
|
||||
dx, dy := x1-x0, y1f-y0f
|
||||
// A single cell scan.
|
||||
if x0i == x1i {
|
||||
r.area += int((x0f + x1f) * dy)
|
||||
r.cover += int(dy)
|
||||
return
|
||||
}
|
||||
// There are at least two cells. Apart from the first and last cells,
|
||||
// all intermediate cells go through the full width of the cell,
|
||||
// or 256 units in 24.8 fixed point format.
|
||||
var (
|
||||
p, q, edge0, edge1 Fix32
|
||||
xiDelta int
|
||||
)
|
||||
if dx > 0 {
|
||||
p, q = (256-x0f)*dy, dx
|
||||
edge0, edge1, xiDelta = 0, 256, 1
|
||||
} else {
|
||||
p, q = x0f*dy, -dx
|
||||
edge0, edge1, xiDelta = 256, 0, -1
|
||||
}
|
||||
yDelta, yRem := p/q, p%q
|
||||
if yRem < 0 {
|
||||
yDelta -= 1
|
||||
yRem += q
|
||||
}
|
||||
// Do the first cell.
|
||||
xi, y := x0i, y0f
|
||||
r.area += int((x0f + edge1) * yDelta)
|
||||
r.cover += int(yDelta)
|
||||
xi, y = xi+xiDelta, y+yDelta
|
||||
r.setCell(xi, yi)
|
||||
if xi != x1i {
|
||||
// Do all the intermediate cells.
|
||||
p = 256 * (y1f - y + yDelta)
|
||||
fullDelta, fullRem := p/q, p%q
|
||||
if fullRem < 0 {
|
||||
fullDelta -= 1
|
||||
fullRem += q
|
||||
}
|
||||
yRem -= q
|
||||
for xi != x1i {
|
||||
yDelta = fullDelta
|
||||
yRem += fullRem
|
||||
if yRem >= 0 {
|
||||
yDelta += 1
|
||||
yRem -= q
|
||||
}
|
||||
r.area += int(256 * yDelta)
|
||||
r.cover += int(yDelta)
|
||||
xi, y = xi+xiDelta, y+yDelta
|
||||
r.setCell(xi, yi)
|
||||
}
|
||||
}
|
||||
// Do the last cell.
|
||||
yDelta = y1f - y
|
||||
r.area += int((edge0 + x1f) * yDelta)
|
||||
r.cover += int(yDelta)
|
||||
}
|
||||
|
||||
// Start starts a new curve at the given point.
|
||||
func (r *Rasterizer) Start(a Point) {
|
||||
r.setCell(int(a.X/256), int(a.Y/256))
|
||||
r.a = a
|
||||
}
|
||||
|
||||
// Add1 adds a linear segment to the current curve.
|
||||
func (r *Rasterizer) Add1(b Point) {
|
||||
x0, y0 := r.a.X, r.a.Y
|
||||
x1, y1 := b.X, b.Y
|
||||
dx, dy := x1-x0, y1-y0
|
||||
// Break the 24.8 fixed point Y co-ordinates into integral and fractional parts.
|
||||
y0i := int(y0) / 256
|
||||
y0f := y0 - Fix32(256*y0i)
|
||||
y1i := int(y1) / 256
|
||||
y1f := y1 - Fix32(256*y1i)
|
||||
|
||||
if y0i == y1i {
|
||||
// There is only one scanline.
|
||||
r.scan(y0i, x0, y0f, x1, y1f)
|
||||
|
||||
} else if dx == 0 {
|
||||
// This is a vertical line segment. We avoid calling r.scan and instead
|
||||
// manipulate r.area and r.cover directly.
|
||||
var (
|
||||
edge0, edge1 Fix32
|
||||
yiDelta int
|
||||
)
|
||||
if dy > 0 {
|
||||
edge0, edge1, yiDelta = 0, 256, 1
|
||||
} else {
|
||||
edge0, edge1, yiDelta = 256, 0, -1
|
||||
}
|
||||
x0i, yi := int(x0)/256, y0i
|
||||
x0fTimes2 := (int(x0) - (256 * x0i)) * 2
|
||||
// Do the first pixel.
|
||||
dcover := int(edge1 - y0f)
|
||||
darea := int(x0fTimes2 * dcover)
|
||||
r.area += darea
|
||||
r.cover += dcover
|
||||
yi += yiDelta
|
||||
r.setCell(x0i, yi)
|
||||
// Do all the intermediate pixels.
|
||||
dcover = int(edge1 - edge0)
|
||||
darea = int(x0fTimes2 * dcover)
|
||||
for yi != y1i {
|
||||
r.area += darea
|
||||
r.cover += dcover
|
||||
yi += yiDelta
|
||||
r.setCell(x0i, yi)
|
||||
}
|
||||
// Do the last pixel.
|
||||
dcover = int(y1f - edge0)
|
||||
darea = int(x0fTimes2 * dcover)
|
||||
r.area += darea
|
||||
r.cover += dcover
|
||||
|
||||
} else {
|
||||
// There are at least two scanlines. Apart from the first and last scanlines,
|
||||
// all intermediate scanlines go through the full height of the row, or 256
|
||||
// units in 24.8 fixed point format.
|
||||
var (
|
||||
p, q, edge0, edge1 Fix32
|
||||
yiDelta int
|
||||
)
|
||||
if dy > 0 {
|
||||
p, q = (256-y0f)*dx, dy
|
||||
edge0, edge1, yiDelta = 0, 256, 1
|
||||
} else {
|
||||
p, q = y0f*dx, -dy
|
||||
edge0, edge1, yiDelta = 256, 0, -1
|
||||
}
|
||||
xDelta, xRem := p/q, p%q
|
||||
if xRem < 0 {
|
||||
xDelta -= 1
|
||||
xRem += q
|
||||
}
|
||||
// Do the first scanline.
|
||||
x, yi := x0, y0i
|
||||
r.scan(yi, x, y0f, x+xDelta, edge1)
|
||||
x, yi = x+xDelta, yi+yiDelta
|
||||
r.setCell(int(x)/256, yi)
|
||||
if yi != y1i {
|
||||
// Do all the intermediate scanlines.
|
||||
p = 256 * dx
|
||||
fullDelta, fullRem := p/q, p%q
|
||||
if fullRem < 0 {
|
||||
fullDelta -= 1
|
||||
fullRem += q
|
||||
}
|
||||
xRem -= q
|
||||
for yi != y1i {
|
||||
xDelta = fullDelta
|
||||
xRem += fullRem
|
||||
if xRem >= 0 {
|
||||
xDelta += 1
|
||||
xRem -= q
|
||||
}
|
||||
r.scan(yi, x, edge0, x+xDelta, edge1)
|
||||
x, yi = x+xDelta, yi+yiDelta
|
||||
r.setCell(int(x)/256, yi)
|
||||
}
|
||||
}
|
||||
// Do the last scanline.
|
||||
r.scan(yi, x, edge0, x1, y1f)
|
||||
}
|
||||
// The next lineTo starts from b.
|
||||
r.a = b
|
||||
}
|
||||
|
||||
// Add2 adds a quadratic segment to the current curve.
|
||||
func (r *Rasterizer) Add2(b, c Point) {
|
||||
// Calculate nSplit (the number of recursive decompositions) based on how `curvy' it is.
|
||||
// Specifically, how much the middle point b deviates from (a+c)/2.
|
||||
dev := maxAbs(r.a.X-2*b.X+c.X, r.a.Y-2*b.Y+c.Y) / Fix32(r.splitScale2)
|
||||
nsplit := 0
|
||||
for dev > 0 {
|
||||
dev /= 4
|
||||
nsplit++
|
||||
}
|
||||
// dev is 32-bit, and nsplit++ every time we shift off 2 bits, so maxNsplit is 16.
|
||||
const maxNsplit = 16
|
||||
if nsplit > maxNsplit {
|
||||
panic("freetype/raster: Add2 nsplit too large: " + strconv.Itoa(nsplit))
|
||||
}
|
||||
// Recursively decompose the curve nSplit levels deep.
|
||||
var (
|
||||
pStack [2*maxNsplit + 3]Point
|
||||
sStack [maxNsplit + 1]int
|
||||
i int
|
||||
)
|
||||
sStack[0] = nsplit
|
||||
pStack[0] = c
|
||||
pStack[1] = b
|
||||
pStack[2] = r.a
|
||||
for i >= 0 {
|
||||
s := sStack[i]
|
||||
p := pStack[2*i:]
|
||||
if s > 0 {
|
||||
// Split the quadratic curve p[:3] into an equivalent set of two shorter curves:
|
||||
// p[:3] and p[2:5]. The new p[4] is the old p[2], and p[0] is unchanged.
|
||||
mx := p[1].X
|
||||
p[4].X = p[2].X
|
||||
p[3].X = (p[4].X + mx) / 2
|
||||
p[1].X = (p[0].X + mx) / 2
|
||||
p[2].X = (p[1].X + p[3].X) / 2
|
||||
my := p[1].Y
|
||||
p[4].Y = p[2].Y
|
||||
p[3].Y = (p[4].Y + my) / 2
|
||||
p[1].Y = (p[0].Y + my) / 2
|
||||
p[2].Y = (p[1].Y + p[3].Y) / 2
|
||||
// The two shorter curves have one less split to do.
|
||||
sStack[i] = s - 1
|
||||
sStack[i+1] = s - 1
|
||||
i++
|
||||
} else {
|
||||
// Replace the level-0 quadratic with a two-linear-piece approximation.
|
||||
midx := (p[0].X + 2*p[1].X + p[2].X) / 4
|
||||
midy := (p[0].Y + 2*p[1].Y + p[2].Y) / 4
|
||||
r.Add1(Point{midx, midy})
|
||||
r.Add1(p[0])
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add3 adds a cubic segment to the current curve.
|
||||
func (r *Rasterizer) Add3(b, c, d Point) {
|
||||
// Calculate nSplit (the number of recursive decompositions) based on how `curvy' it is.
|
||||
dev2 := maxAbs(r.a.X-3*(b.X+c.X)+d.X, r.a.Y-3*(b.Y+c.Y)+d.Y) / Fix32(r.splitScale2)
|
||||
dev3 := maxAbs(r.a.X-2*b.X+d.X, r.a.Y-2*b.Y+d.Y) / Fix32(r.splitScale3)
|
||||
nsplit := 0
|
||||
for dev2 > 0 || dev3 > 0 {
|
||||
dev2 /= 8
|
||||
dev3 /= 4
|
||||
nsplit++
|
||||
}
|
||||
// devN is 32-bit, and nsplit++ every time we shift off 2 bits, so maxNsplit is 16.
|
||||
const maxNsplit = 16
|
||||
if nsplit > maxNsplit {
|
||||
panic("freetype/raster: Add3 nsplit too large: " + strconv.Itoa(nsplit))
|
||||
}
|
||||
// Recursively decompose the curve nSplit levels deep.
|
||||
var (
|
||||
pStack [3*maxNsplit + 4]Point
|
||||
sStack [maxNsplit + 1]int
|
||||
i int
|
||||
)
|
||||
sStack[0] = nsplit
|
||||
pStack[0] = d
|
||||
pStack[1] = c
|
||||
pStack[2] = b
|
||||
pStack[3] = r.a
|
||||
for i >= 0 {
|
||||
s := sStack[i]
|
||||
p := pStack[3*i:]
|
||||
if s > 0 {
|
||||
// Split the cubic curve p[:4] into an equivalent set of two shorter curves:
|
||||
// p[:4] and p[3:7]. The new p[6] is the old p[3], and p[0] is unchanged.
|
||||
m01x := (p[0].X + p[1].X) / 2
|
||||
m12x := (p[1].X + p[2].X) / 2
|
||||
m23x := (p[2].X + p[3].X) / 2
|
||||
p[6].X = p[3].X
|
||||
p[5].X = m23x
|
||||
p[1].X = m01x
|
||||
p[2].X = (m01x + m12x) / 2
|
||||
p[4].X = (m12x + m23x) / 2
|
||||
p[3].X = (p[2].X + p[4].X) / 2
|
||||
m01y := (p[0].Y + p[1].Y) / 2
|
||||
m12y := (p[1].Y + p[2].Y) / 2
|
||||
m23y := (p[2].Y + p[3].Y) / 2
|
||||
p[6].Y = p[3].Y
|
||||
p[5].Y = m23y
|
||||
p[1].Y = m01y
|
||||
p[2].Y = (m01y + m12y) / 2
|
||||
p[4].Y = (m12y + m23y) / 2
|
||||
p[3].Y = (p[2].Y + p[4].Y) / 2
|
||||
// The two shorter curves have one less split to do.
|
||||
sStack[i] = s - 1
|
||||
sStack[i+1] = s - 1
|
||||
i++
|
||||
} else {
|
||||
// Replace the level-0 cubic with a two-linear-piece approximation.
|
||||
midx := (p[0].X + 3*(p[1].X+p[2].X) + p[3].X) / 8
|
||||
midy := (p[0].Y + 3*(p[1].Y+p[2].Y) + p[3].Y) / 8
|
||||
r.Add1(Point{midx, midy})
|
||||
r.Add1(p[0])
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddPath adds the given Path.
|
||||
func (r *Rasterizer) AddPath(p Path) {
|
||||
for i := 0; i < len(p); {
|
||||
switch p[i] {
|
||||
case 0:
|
||||
r.Start(Point{p[i+1], p[i+2]})
|
||||
i += 4
|
||||
case 1:
|
||||
r.Add1(Point{p[i+1], p[i+2]})
|
||||
i += 4
|
||||
case 2:
|
||||
r.Add2(Point{p[i+1], p[i+2]}, Point{p[i+3], p[i+4]})
|
||||
i += 6
|
||||
case 3:
|
||||
r.Add3(Point{p[i+1], p[i+2]}, Point{p[i+3], p[i+4]}, Point{p[i+5], p[i+6]})
|
||||
i += 8
|
||||
default:
|
||||
panic("freetype/raster: bad path")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddStroke adds a stroked Path.
|
||||
func (r *Rasterizer) AddStroke(q Path, width Fix32, cr Capper, jr Joiner) {
|
||||
Stroke(r, q, width, cr, jr)
|
||||
}
|
||||
|
||||
// Converts an area value to a uint32 alpha value. A completely filled pixel
|
||||
// corresponds to an area of 256*256*2, and an alpha of 1<<32-1. The
|
||||
// conversion of area values greater than this depends on the winding rule:
|
||||
// even-odd or non-zero.
|
||||
func (r *Rasterizer) areaToAlpha(area int) uint32 {
|
||||
// The C Freetype implementation (version 2.3.12) does "alpha := area>>1" without
|
||||
// the +1. Round-to-nearest gives a more symmetric result than round-down.
|
||||
// The C implementation also returns 8-bit alpha, not 32-bit alpha.
|
||||
a := (area + 1) >> 1
|
||||
if a < 0 {
|
||||
a = -a
|
||||
}
|
||||
alpha := uint32(a)
|
||||
if r.UseNonZeroWinding {
|
||||
if alpha > 0xffff {
|
||||
alpha = 0xffff
|
||||
}
|
||||
} else {
|
||||
alpha &= 0x1ffff
|
||||
if alpha > 0x10000 {
|
||||
alpha = 0x20000 - alpha
|
||||
} else if alpha == 0x10000 {
|
||||
alpha = 0x0ffff
|
||||
}
|
||||
}
|
||||
alpha |= alpha << 16
|
||||
return alpha
|
||||
}
|
||||
|
||||
// Rasterize converts r's accumulated curves into Spans for p. The Spans
|
||||
// passed to p are non-overlapping, and sorted by Y and then X. They all
|
||||
// have non-zero width (and 0 <= X0 < X1 <= r.width) and non-zero A, except
|
||||
// for the final Span, which has Y, X0, X1 and A all equal to zero.
|
||||
func (r *Rasterizer) Rasterize(p Painter) {
|
||||
r.saveCell()
|
||||
s := 0
|
||||
for yi := 0; yi < len(r.cellIndex); yi++ {
|
||||
xi, cover := 0, 0
|
||||
for c := r.cellIndex[yi]; c != -1; c = r.cell[c].next {
|
||||
if cover != 0 && r.cell[c].xi > xi {
|
||||
alpha := r.areaToAlpha(cover * 256 * 2)
|
||||
if alpha != 0 {
|
||||
xi0, xi1 := xi, r.cell[c].xi
|
||||
if xi0 < 0 {
|
||||
xi0 = 0
|
||||
}
|
||||
if xi1 >= r.width {
|
||||
xi1 = r.width
|
||||
}
|
||||
if xi0 < xi1 {
|
||||
r.spanBuf[s] = Span{yi + r.Dy, xi0 + r.Dx, xi1 + r.Dx, alpha}
|
||||
s++
|
||||
}
|
||||
}
|
||||
}
|
||||
cover += r.cell[c].cover
|
||||
alpha := r.areaToAlpha(cover*256*2 - r.cell[c].area)
|
||||
xi = r.cell[c].xi + 1
|
||||
if alpha != 0 {
|
||||
xi0, xi1 := r.cell[c].xi, xi
|
||||
if xi0 < 0 {
|
||||
xi0 = 0
|
||||
}
|
||||
if xi1 >= r.width {
|
||||
xi1 = r.width
|
||||
}
|
||||
if xi0 < xi1 {
|
||||
r.spanBuf[s] = Span{yi + r.Dy, xi0 + r.Dx, xi1 + r.Dx, alpha}
|
||||
s++
|
||||
}
|
||||
}
|
||||
if s > len(r.spanBuf)-2 {
|
||||
p.Paint(r.spanBuf[:s], false)
|
||||
s = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
p.Paint(r.spanBuf[:s], true)
|
||||
}
|
||||
|
||||
// Clear cancels any previous calls to r.Start or r.AddXxx.
|
||||
func (r *Rasterizer) Clear() {
|
||||
r.a = Point{}
|
||||
r.xi = 0
|
||||
r.yi = 0
|
||||
r.area = 0
|
||||
r.cover = 0
|
||||
r.cell = r.cell[:0]
|
||||
for i := 0; i < len(r.cellIndex); i++ {
|
||||
r.cellIndex[i] = -1
|
||||
}
|
||||
}
|
||||
|
||||
// SetBounds sets the maximum width and height of the rasterized image and
|
||||
// calls Clear. The width and height are in pixels, not Fix32 units.
|
||||
func (r *Rasterizer) SetBounds(width, height int) {
|
||||
if width < 0 {
|
||||
width = 0
|
||||
}
|
||||
if height < 0 {
|
||||
height = 0
|
||||
}
|
||||
// Use the same ssN heuristic as the C Freetype implementation.
|
||||
// The C implementation uses the values 32, 16, but those are in
|
||||
// 26.6 fixed point units, and we use 24.8 fixed point everywhere.
|
||||
ss2, ss3 := 128, 64
|
||||
if width > 24 || height > 24 {
|
||||
ss2, ss3 = 2*ss2, 2*ss3
|
||||
if width > 120 || height > 120 {
|
||||
ss2, ss3 = 2*ss2, 2*ss3
|
||||
}
|
||||
}
|
||||
r.width = width
|
||||
r.splitScale2 = ss2
|
||||
r.splitScale3 = ss3
|
||||
r.cell = r.cellBuf[:0]
|
||||
if height > len(r.cellIndexBuf) {
|
||||
r.cellIndex = make([]int, height)
|
||||
} else {
|
||||
r.cellIndex = r.cellIndexBuf[:height]
|
||||
}
|
||||
r.Clear()
|
||||
}
|
||||
|
||||
// NewRasterizer creates a new Rasterizer with the given bounds.
|
||||
func NewRasterizer(width, height int) *Rasterizer {
|
||||
r := new(Rasterizer)
|
||||
r.SetBounds(width, height)
|
||||
return r
|
||||
}
|
||||
466
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/stroke.go
сгенерированный
поставляемый
466
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/raster/stroke.go
сгенерированный
поставляемый
@@ -1,466 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package raster
|
||||
|
||||
// Two points are considered practically equal if the square of the distance
|
||||
// between them is less than one quarter (i.e. 16384 / 65536 in Fix64).
|
||||
const epsilon = 16384
|
||||
|
||||
// A Capper signifies how to begin or end a stroked path.
|
||||
type Capper interface {
|
||||
// Cap adds a cap to p given a pivot point and the normal vector of a
|
||||
// terminal segment. The normal's length is half of the stroke width.
|
||||
Cap(p Adder, halfWidth Fix32, pivot, n1 Point)
|
||||
}
|
||||
|
||||
// The CapperFunc type adapts an ordinary function to be a Capper.
|
||||
type CapperFunc func(Adder, Fix32, Point, Point)
|
||||
|
||||
func (f CapperFunc) Cap(p Adder, halfWidth Fix32, pivot, n1 Point) {
|
||||
f(p, halfWidth, pivot, n1)
|
||||
}
|
||||
|
||||
// A Joiner signifies how to join interior nodes of a stroked path.
|
||||
type Joiner interface {
|
||||
// Join adds a join to the two sides of a stroked path given a pivot
|
||||
// point and the normal vectors of the trailing and leading segments.
|
||||
// Both normals have length equal to half of the stroke width.
|
||||
Join(lhs, rhs Adder, halfWidth Fix32, pivot, n0, n1 Point)
|
||||
}
|
||||
|
||||
// The JoinerFunc type adapts an ordinary function to be a Joiner.
|
||||
type JoinerFunc func(lhs, rhs Adder, halfWidth Fix32, pivot, n0, n1 Point)
|
||||
|
||||
func (f JoinerFunc) Join(lhs, rhs Adder, halfWidth Fix32, pivot, n0, n1 Point) {
|
||||
f(lhs, rhs, halfWidth, pivot, n0, n1)
|
||||
}
|
||||
|
||||
// RoundCapper adds round caps to a stroked path.
|
||||
var RoundCapper Capper = CapperFunc(roundCapper)
|
||||
|
||||
func roundCapper(p Adder, halfWidth Fix32, pivot, n1 Point) {
|
||||
// The cubic Bézier approximation to a circle involves the magic number
|
||||
// (√2 - 1) * 4/3, which is approximately 141/256.
|
||||
const k = 141
|
||||
e := n1.Rot90CCW()
|
||||
side := pivot.Add(e)
|
||||
start, end := pivot.Sub(n1), pivot.Add(n1)
|
||||
d, e := n1.Mul(k), e.Mul(k)
|
||||
p.Add3(start.Add(e), side.Sub(d), side)
|
||||
p.Add3(side.Add(d), end.Add(e), end)
|
||||
}
|
||||
|
||||
// ButtCapper adds butt caps to a stroked path.
|
||||
var ButtCapper Capper = CapperFunc(buttCapper)
|
||||
|
||||
func buttCapper(p Adder, halfWidth Fix32, pivot, n1 Point) {
|
||||
p.Add1(pivot.Add(n1))
|
||||
}
|
||||
|
||||
// SquareCapper adds square caps to a stroked path.
|
||||
var SquareCapper Capper = CapperFunc(squareCapper)
|
||||
|
||||
func squareCapper(p Adder, halfWidth Fix32, pivot, n1 Point) {
|
||||
e := n1.Rot90CCW()
|
||||
side := pivot.Add(e)
|
||||
p.Add1(side.Sub(n1))
|
||||
p.Add1(side.Add(n1))
|
||||
p.Add1(pivot.Add(n1))
|
||||
}
|
||||
|
||||
// RoundJoiner adds round joins to a stroked path.
|
||||
var RoundJoiner Joiner = JoinerFunc(roundJoiner)
|
||||
|
||||
func roundJoiner(lhs, rhs Adder, haflWidth Fix32, pivot, n0, n1 Point) {
|
||||
dot := n0.Rot90CW().Dot(n1)
|
||||
if dot >= 0 {
|
||||
addArc(lhs, pivot, n0, n1)
|
||||
rhs.Add1(pivot.Sub(n1))
|
||||
} else {
|
||||
lhs.Add1(pivot.Add(n1))
|
||||
addArc(rhs, pivot, n0.Neg(), n1.Neg())
|
||||
}
|
||||
}
|
||||
|
||||
// BevelJoiner adds bevel joins to a stroked path.
|
||||
var BevelJoiner Joiner = JoinerFunc(bevelJoiner)
|
||||
|
||||
func bevelJoiner(lhs, rhs Adder, haflWidth Fix32, pivot, n0, n1 Point) {
|
||||
lhs.Add1(pivot.Add(n1))
|
||||
rhs.Add1(pivot.Sub(n1))
|
||||
}
|
||||
|
||||
// addArc adds a circular arc from pivot+n0 to pivot+n1 to p. The shorter of
|
||||
// the two possible arcs is taken, i.e. the one spanning <= 180 degrees.
|
||||
// The two vectors n0 and n1 must be of equal length.
|
||||
func addArc(p Adder, pivot, n0, n1 Point) {
|
||||
// r2 is the square of the length of n0.
|
||||
r2 := n0.Dot(n0)
|
||||
if r2 < epsilon {
|
||||
// The arc radius is so small that we collapse to a straight line.
|
||||
p.Add1(pivot.Add(n1))
|
||||
return
|
||||
}
|
||||
// We approximate the arc by 0, 1, 2 or 3 45-degree quadratic segments plus
|
||||
// a final quadratic segment from s to n1. Each 45-degree segment has control
|
||||
// points {1, 0}, {1, tan(π/8)} and {1/√2, 1/√2} suitably scaled, rotated and
|
||||
// translated. tan(π/8) is approximately 106/256.
|
||||
const tpo8 = 106
|
||||
var s Point
|
||||
// We determine which octant the angle between n0 and n1 is in via three dot products.
|
||||
// m0, m1 and m2 are n0 rotated clockwise by 45, 90 and 135 degrees.
|
||||
m0 := n0.Rot45CW()
|
||||
m1 := n0.Rot90CW()
|
||||
m2 := m0.Rot90CW()
|
||||
if m1.Dot(n1) >= 0 {
|
||||
if n0.Dot(n1) >= 0 {
|
||||
if m2.Dot(n1) <= 0 {
|
||||
// n1 is between 0 and 45 degrees clockwise of n0.
|
||||
s = n0
|
||||
} else {
|
||||
// n1 is between 45 and 90 degrees clockwise of n0.
|
||||
p.Add2(pivot.Add(n0).Add(m1.Mul(tpo8)), pivot.Add(m0))
|
||||
s = m0
|
||||
}
|
||||
} else {
|
||||
pm1, n0t := pivot.Add(m1), n0.Mul(tpo8)
|
||||
p.Add2(pivot.Add(n0).Add(m1.Mul(tpo8)), pivot.Add(m0))
|
||||
p.Add2(pm1.Add(n0t), pm1)
|
||||
if m0.Dot(n1) >= 0 {
|
||||
// n1 is between 90 and 135 degrees clockwise of n0.
|
||||
s = m1
|
||||
} else {
|
||||
// n1 is between 135 and 180 degrees clockwise of n0.
|
||||
p.Add2(pm1.Sub(n0t), pivot.Add(m2))
|
||||
s = m2
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if n0.Dot(n1) >= 0 {
|
||||
if m0.Dot(n1) >= 0 {
|
||||
// n1 is between 0 and 45 degrees counter-clockwise of n0.
|
||||
s = n0
|
||||
} else {
|
||||
// n1 is between 45 and 90 degrees counter-clockwise of n0.
|
||||
p.Add2(pivot.Add(n0).Sub(m1.Mul(tpo8)), pivot.Sub(m2))
|
||||
s = m2.Neg()
|
||||
}
|
||||
} else {
|
||||
pm1, n0t := pivot.Sub(m1), n0.Mul(tpo8)
|
||||
p.Add2(pivot.Add(n0).Sub(m1.Mul(tpo8)), pivot.Sub(m2))
|
||||
p.Add2(pm1.Add(n0t), pm1)
|
||||
if m2.Dot(n1) <= 0 {
|
||||
// n1 is between 90 and 135 degrees counter-clockwise of n0.
|
||||
s = m1.Neg()
|
||||
} else {
|
||||
// n1 is between 135 and 180 degrees counter-clockwise of n0.
|
||||
p.Add2(pm1.Sub(n0t), pivot.Sub(m0))
|
||||
s = m0.Neg()
|
||||
}
|
||||
}
|
||||
}
|
||||
// The final quadratic segment has two endpoints s and n1 and the middle
|
||||
// control point is a multiple of s.Add(n1), i.e. it is on the angle bisector
|
||||
// of those two points. The multiple ranges between 128/256 and 150/256 as
|
||||
// the angle between s and n1 ranges between 0 and 45 degrees.
|
||||
// When the angle is 0 degrees (i.e. s and n1 are coincident) then s.Add(n1)
|
||||
// is twice s and so the middle control point of the degenerate quadratic
|
||||
// segment should be half s.Add(n1), and half = 128/256.
|
||||
// When the angle is 45 degrees then 150/256 is the ratio of the lengths of
|
||||
// the two vectors {1, tan(π/8)} and {1 + 1/√2, 1/√2}.
|
||||
// d is the normalized dot product between s and n1. Since the angle ranges
|
||||
// between 0 and 45 degrees then d ranges between 256/256 and 181/256.
|
||||
d := 256 * s.Dot(n1) / r2
|
||||
multiple := Fix32(150 - 22*(d-181)/(256-181))
|
||||
p.Add2(pivot.Add(s.Add(n1).Mul(multiple)), pivot.Add(n1))
|
||||
}
|
||||
|
||||
// midpoint returns the midpoint of two Points.
|
||||
func midpoint(a, b Point) Point {
|
||||
return Point{(a.X + b.X) / 2, (a.Y + b.Y) / 2}
|
||||
}
|
||||
|
||||
// angleGreaterThan45 returns whether the angle between two vectors is more
|
||||
// than 45 degrees.
|
||||
func angleGreaterThan45(v0, v1 Point) bool {
|
||||
v := v0.Rot45CCW()
|
||||
return v.Dot(v1) < 0 || v.Rot90CW().Dot(v1) < 0
|
||||
}
|
||||
|
||||
// interpolate returns the point (1-t)*a + t*b.
|
||||
func interpolate(a, b Point, t Fix64) Point {
|
||||
s := 65536 - t
|
||||
x := s*Fix64(a.X) + t*Fix64(b.X)
|
||||
y := s*Fix64(a.Y) + t*Fix64(b.Y)
|
||||
return Point{Fix32(x >> 16), Fix32(y >> 16)}
|
||||
}
|
||||
|
||||
// curviest2 returns the value of t for which the quadratic parametric curve
|
||||
// (1-t)²*a + 2*t*(1-t).b + t²*c has maximum curvature.
|
||||
//
|
||||
// The curvature of the parametric curve f(t) = (x(t), y(t)) is
|
||||
// |x′y″-y′x″| / (x′²+y′²)^(3/2).
|
||||
//
|
||||
// Let d = b-a and e = c-2*b+a, so that f′(t) = 2*d+2*e*t and f″(t) = 2*e.
|
||||
// The curvature's numerator is (2*dx+2*ex*t)*(2*ey)-(2*dy+2*ey*t)*(2*ex),
|
||||
// which simplifies to 4*dx*ey-4*dy*ex, which is constant with respect to t.
|
||||
//
|
||||
// Thus, curvature is extreme where the denominator is extreme, i.e. where
|
||||
// (x′²+y′²) is extreme. The first order condition is that
|
||||
// 2*x′*x″+2*y′*y″ = 0, or (dx+ex*t)*ex + (dy+ey*t)*ey = 0.
|
||||
// Solving for t gives t = -(dx*ex+dy*ey) / (ex*ex+ey*ey).
|
||||
func curviest2(a, b, c Point) Fix64 {
|
||||
dx := int64(b.X - a.X)
|
||||
dy := int64(b.Y - a.Y)
|
||||
ex := int64(c.X - 2*b.X + a.X)
|
||||
ey := int64(c.Y - 2*b.Y + a.Y)
|
||||
if ex == 0 && ey == 0 {
|
||||
return 32768
|
||||
}
|
||||
return Fix64(-65536 * (dx*ex + dy*ey) / (ex*ex + ey*ey))
|
||||
}
|
||||
|
||||
// A stroker holds state for stroking a path.
|
||||
type stroker struct {
|
||||
// p is the destination that records the stroked path.
|
||||
p Adder
|
||||
// u is the half-width of the stroke.
|
||||
u Fix32
|
||||
// cr and jr specify how to end and connect path segments.
|
||||
cr Capper
|
||||
jr Joiner
|
||||
// r is the reverse path. Stroking a path involves constructing two
|
||||
// parallel paths 2*u apart. The first path is added immediately to p,
|
||||
// the second path is accumulated in r and eventually added in reverse.
|
||||
r Path
|
||||
// a is the most recent segment point. anorm is the segment normal of
|
||||
// length u at that point.
|
||||
a, anorm Point
|
||||
}
|
||||
|
||||
// addNonCurvy2 adds a quadratic segment to the stroker, where the segment
|
||||
// defined by (k.a, b, c) achieves maximum curvature at either k.a or c.
|
||||
func (k *stroker) addNonCurvy2(b, c Point) {
|
||||
// We repeatedly divide the segment at its middle until it is straight
|
||||
// enough to approximate the stroke by just translating the control points.
|
||||
// ds and ps are stacks of depths and points. t is the top of the stack.
|
||||
const maxDepth = 5
|
||||
var (
|
||||
ds [maxDepth + 1]int
|
||||
ps [2*maxDepth + 3]Point
|
||||
t int
|
||||
)
|
||||
// Initially the ps stack has one quadratic segment of depth zero.
|
||||
ds[0] = 0
|
||||
ps[2] = k.a
|
||||
ps[1] = b
|
||||
ps[0] = c
|
||||
anorm := k.anorm
|
||||
var cnorm Point
|
||||
|
||||
for {
|
||||
depth := ds[t]
|
||||
a := ps[2*t+2]
|
||||
b := ps[2*t+1]
|
||||
c := ps[2*t+0]
|
||||
ab := b.Sub(a)
|
||||
bc := c.Sub(b)
|
||||
abIsSmall := ab.Dot(ab) < Fix64(1<<16)
|
||||
bcIsSmall := bc.Dot(bc) < Fix64(1<<16)
|
||||
if abIsSmall && bcIsSmall {
|
||||
// Approximate the segment by a circular arc.
|
||||
cnorm = bc.Norm(k.u).Rot90CCW()
|
||||
mac := midpoint(a, c)
|
||||
addArc(k.p, mac, anorm, cnorm)
|
||||
addArc(&k.r, mac, anorm.Neg(), cnorm.Neg())
|
||||
} else if depth < maxDepth && angleGreaterThan45(ab, bc) {
|
||||
// Divide the segment in two and push both halves on the stack.
|
||||
mab := midpoint(a, b)
|
||||
mbc := midpoint(b, c)
|
||||
t++
|
||||
ds[t+0] = depth + 1
|
||||
ds[t-1] = depth + 1
|
||||
ps[2*t+2] = a
|
||||
ps[2*t+1] = mab
|
||||
ps[2*t+0] = midpoint(mab, mbc)
|
||||
ps[2*t-1] = mbc
|
||||
continue
|
||||
} else {
|
||||
// Translate the control points.
|
||||
bnorm := c.Sub(a).Norm(k.u).Rot90CCW()
|
||||
cnorm = bc.Norm(k.u).Rot90CCW()
|
||||
k.p.Add2(b.Add(bnorm), c.Add(cnorm))
|
||||
k.r.Add2(b.Sub(bnorm), c.Sub(cnorm))
|
||||
}
|
||||
if t == 0 {
|
||||
k.a, k.anorm = c, cnorm
|
||||
return
|
||||
}
|
||||
t--
|
||||
anorm = cnorm
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// Add1 adds a linear segment to the stroker.
|
||||
func (k *stroker) Add1(b Point) {
|
||||
bnorm := b.Sub(k.a).Norm(k.u).Rot90CCW()
|
||||
if len(k.r) == 0 {
|
||||
k.p.Start(k.a.Add(bnorm))
|
||||
k.r.Start(k.a.Sub(bnorm))
|
||||
} else {
|
||||
k.jr.Join(k.p, &k.r, k.u, k.a, k.anorm, bnorm)
|
||||
}
|
||||
k.p.Add1(b.Add(bnorm))
|
||||
k.r.Add1(b.Sub(bnorm))
|
||||
k.a, k.anorm = b, bnorm
|
||||
}
|
||||
|
||||
// Add2 adds a quadratic segment to the stroker.
|
||||
func (k *stroker) Add2(b, c Point) {
|
||||
ab := b.Sub(k.a)
|
||||
bc := c.Sub(b)
|
||||
abnorm := ab.Norm(k.u).Rot90CCW()
|
||||
if len(k.r) == 0 {
|
||||
k.p.Start(k.a.Add(abnorm))
|
||||
k.r.Start(k.a.Sub(abnorm))
|
||||
} else {
|
||||
k.jr.Join(k.p, &k.r, k.u, k.a, k.anorm, abnorm)
|
||||
}
|
||||
|
||||
// Approximate nearly-degenerate quadratics by linear segments.
|
||||
abIsSmall := ab.Dot(ab) < epsilon
|
||||
bcIsSmall := bc.Dot(bc) < epsilon
|
||||
if abIsSmall || bcIsSmall {
|
||||
acnorm := c.Sub(k.a).Norm(k.u).Rot90CCW()
|
||||
k.p.Add1(c.Add(acnorm))
|
||||
k.r.Add1(c.Sub(acnorm))
|
||||
k.a, k.anorm = c, acnorm
|
||||
return
|
||||
}
|
||||
|
||||
// The quadratic segment (k.a, b, c) has a point of maximum curvature.
|
||||
// If this occurs at an end point, we process the segment as a whole.
|
||||
t := curviest2(k.a, b, c)
|
||||
if t <= 0 || t >= 65536 {
|
||||
k.addNonCurvy2(b, c)
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, we perform a de Casteljau decomposition at the point of
|
||||
// maximum curvature and process the two straighter parts.
|
||||
mab := interpolate(k.a, b, t)
|
||||
mbc := interpolate(b, c, t)
|
||||
mabc := interpolate(mab, mbc, t)
|
||||
|
||||
// If the vectors ab and bc are close to being in opposite directions,
|
||||
// then the decomposition can become unstable, so we approximate the
|
||||
// quadratic segment by two linear segments joined by an arc.
|
||||
bcnorm := bc.Norm(k.u).Rot90CCW()
|
||||
if abnorm.Dot(bcnorm) < -Fix64(k.u)*Fix64(k.u)*2047/2048 {
|
||||
pArc := abnorm.Dot(bc) < 0
|
||||
|
||||
k.p.Add1(mabc.Add(abnorm))
|
||||
if pArc {
|
||||
z := abnorm.Rot90CW()
|
||||
addArc(k.p, mabc, abnorm, z)
|
||||
addArc(k.p, mabc, z, bcnorm)
|
||||
}
|
||||
k.p.Add1(mabc.Add(bcnorm))
|
||||
k.p.Add1(c.Add(bcnorm))
|
||||
|
||||
k.r.Add1(mabc.Sub(abnorm))
|
||||
if !pArc {
|
||||
z := abnorm.Rot90CW()
|
||||
addArc(&k.r, mabc, abnorm.Neg(), z)
|
||||
addArc(&k.r, mabc, z, bcnorm.Neg())
|
||||
}
|
||||
k.r.Add1(mabc.Sub(bcnorm))
|
||||
k.r.Add1(c.Sub(bcnorm))
|
||||
|
||||
k.a, k.anorm = c, bcnorm
|
||||
return
|
||||
}
|
||||
|
||||
// Process the decomposed parts.
|
||||
k.addNonCurvy2(mab, mabc)
|
||||
k.addNonCurvy2(mbc, c)
|
||||
}
|
||||
|
||||
// Add3 adds a cubic segment to the stroker.
|
||||
func (k *stroker) Add3(b, c, d Point) {
|
||||
panic("freetype/raster: stroke unimplemented for cubic segments")
|
||||
}
|
||||
|
||||
// stroke adds the stroked Path q to p, where q consists of exactly one curve.
|
||||
func (k *stroker) stroke(q Path) {
|
||||
// Stroking is implemented by deriving two paths each k.u apart from q.
|
||||
// The left-hand-side path is added immediately to k.p; the right-hand-side
|
||||
// path is accumulated in k.r. Once we've finished adding the LHS to k.p,
|
||||
// we add the RHS in reverse order.
|
||||
k.r = make(Path, 0, len(q))
|
||||
k.a = Point{q[1], q[2]}
|
||||
for i := 4; i < len(q); {
|
||||
switch q[i] {
|
||||
case 1:
|
||||
k.Add1(Point{q[i+1], q[i+2]})
|
||||
i += 4
|
||||
case 2:
|
||||
k.Add2(Point{q[i+1], q[i+2]}, Point{q[i+3], q[i+4]})
|
||||
i += 6
|
||||
case 3:
|
||||
k.Add3(Point{q[i+1], q[i+2]}, Point{q[i+3], q[i+4]}, Point{q[i+5], q[i+6]})
|
||||
i += 8
|
||||
default:
|
||||
panic("freetype/raster: bad path")
|
||||
}
|
||||
}
|
||||
if len(k.r) == 0 {
|
||||
return
|
||||
}
|
||||
// TODO(nigeltao): if q is a closed curve then we should join the first and
|
||||
// last segments instead of capping them.
|
||||
k.cr.Cap(k.p, k.u, q.lastPoint(), k.anorm.Neg())
|
||||
addPathReversed(k.p, k.r)
|
||||
pivot := q.firstPoint()
|
||||
k.cr.Cap(k.p, k.u, pivot, pivot.Sub(Point{k.r[1], k.r[2]}))
|
||||
}
|
||||
|
||||
// Stroke adds q stroked with the given width to p. The result is typically
|
||||
// self-intersecting and should be rasterized with UseNonZeroWinding.
|
||||
// cr and jr may be nil, which defaults to a RoundCapper or RoundJoiner.
|
||||
func Stroke(p Adder, q Path, width Fix32, cr Capper, jr Joiner) {
|
||||
if len(q) == 0 {
|
||||
return
|
||||
}
|
||||
if cr == nil {
|
||||
cr = RoundCapper
|
||||
}
|
||||
if jr == nil {
|
||||
jr = RoundJoiner
|
||||
}
|
||||
if q[0] != 0 {
|
||||
panic("freetype/raster: bad path")
|
||||
}
|
||||
s := stroker{p: p, u: width / 2, cr: cr, jr: jr}
|
||||
i := 0
|
||||
for j := 4; j < len(q); {
|
||||
switch q[j] {
|
||||
case 0:
|
||||
s.stroke(q[i:j])
|
||||
i, j = j, j+4
|
||||
case 1:
|
||||
j += 4
|
||||
case 2:
|
||||
j += 6
|
||||
case 3:
|
||||
j += 8
|
||||
default:
|
||||
panic("freetype/raster: bad path")
|
||||
}
|
||||
}
|
||||
s.stroke(q[i:])
|
||||
}
|
||||
530
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go
сгенерированный
поставляемый
530
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/glyph.go
сгенерированный
поставляемый
@@ -1,530 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package truetype
|
||||
|
||||
// Hinting is the policy for snapping a glyph's contours to pixel boundaries.
|
||||
type Hinting int32
|
||||
|
||||
const (
|
||||
// NoHinting means to not perform any hinting.
|
||||
NoHinting Hinting = iota
|
||||
// FullHinting means to use the font's hinting instructions.
|
||||
FullHinting
|
||||
|
||||
// TODO: implement VerticalHinting.
|
||||
)
|
||||
|
||||
// A Point is a co-ordinate pair plus whether it is ``on'' a contour or an
|
||||
// ``off'' control point.
|
||||
type Point struct {
|
||||
X, Y int32
|
||||
// The Flags' LSB means whether or not this Point is ``on'' the contour.
|
||||
// Other bits are reserved for internal use.
|
||||
Flags uint32
|
||||
}
|
||||
|
||||
// A GlyphBuf holds a glyph's contours. A GlyphBuf can be re-used to load a
|
||||
// series of glyphs from a Font.
|
||||
type GlyphBuf struct {
|
||||
// AdvanceWidth is the glyph's advance width.
|
||||
AdvanceWidth int32
|
||||
// B is the glyph's bounding box.
|
||||
B Bounds
|
||||
// Point contains all Points from all contours of the glyph. If
|
||||
// hinting was used to load a glyph then Unhinted contains those
|
||||
// Points before they were hinted, and InFontUnits contains those
|
||||
// Points before they were hinted and scaled.
|
||||
Point, Unhinted, InFontUnits []Point
|
||||
// End is the point indexes of the end point of each countour. The
|
||||
// length of End is the number of contours in the glyph. The i'th
|
||||
// contour consists of points Point[End[i-1]:End[i]], where End[-1]
|
||||
// is interpreted to mean zero.
|
||||
End []int
|
||||
|
||||
font *Font
|
||||
scale int32
|
||||
hinting Hinting
|
||||
hinter hinter
|
||||
// phantomPoints are the co-ordinates of the synthetic phantom points
|
||||
// used for hinting and bounding box calculations.
|
||||
phantomPoints [4]Point
|
||||
// pp1x is the X co-ordinate of the first phantom point. The '1' is
|
||||
// using 1-based indexing; pp1x is almost always phantomPoints[0].X.
|
||||
// TODO: eliminate this and consistently use phantomPoints[0].X.
|
||||
pp1x int32
|
||||
// metricsSet is whether the glyph's metrics have been set yet. For a
|
||||
// compound glyph, a sub-glyph may override the outer glyph's metrics.
|
||||
metricsSet bool
|
||||
// tmp is a scratch buffer.
|
||||
tmp []Point
|
||||
}
|
||||
|
||||
// Flags for decoding a glyph's contours. These flags are documented at
|
||||
// http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html.
|
||||
const (
|
||||
flagOnCurve = 1 << iota
|
||||
flagXShortVector
|
||||
flagYShortVector
|
||||
flagRepeat
|
||||
flagPositiveXShortVector
|
||||
flagPositiveYShortVector
|
||||
|
||||
// The remaining flags are for internal use.
|
||||
flagTouchedX
|
||||
flagTouchedY
|
||||
)
|
||||
|
||||
// The same flag bits (0x10 and 0x20) are overloaded to have two meanings,
|
||||
// dependent on the value of the flag{X,Y}ShortVector bits.
|
||||
const (
|
||||
flagThisXIsSame = flagPositiveXShortVector
|
||||
flagThisYIsSame = flagPositiveYShortVector
|
||||
)
|
||||
|
||||
// Load loads a glyph's contours from a Font, overwriting any previously
|
||||
// loaded contours for this GlyphBuf. scale is the number of 26.6 fixed point
|
||||
// units in 1 em, i is the glyph index, and h is the hinting policy.
|
||||
func (g *GlyphBuf) Load(f *Font, scale int32, i Index, h Hinting) error {
|
||||
g.Point = g.Point[:0]
|
||||
g.Unhinted = g.Unhinted[:0]
|
||||
g.InFontUnits = g.InFontUnits[:0]
|
||||
g.End = g.End[:0]
|
||||
g.font = f
|
||||
g.hinting = h
|
||||
g.scale = scale
|
||||
g.pp1x = 0
|
||||
g.phantomPoints = [4]Point{}
|
||||
g.metricsSet = false
|
||||
|
||||
if h != NoHinting {
|
||||
if err := g.hinter.init(f, scale); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.load(0, i, true); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: this selection of either g.pp1x or g.phantomPoints[0].X isn't ideal,
|
||||
// and should be cleaned up once we have all the testScaling tests passing,
|
||||
// plus additional tests for Freetype-Go's bounding boxes matching C Freetype's.
|
||||
pp1x := g.pp1x
|
||||
if h != NoHinting {
|
||||
pp1x = g.phantomPoints[0].X
|
||||
}
|
||||
if pp1x != 0 {
|
||||
for i := range g.Point {
|
||||
g.Point[i].X -= pp1x
|
||||
}
|
||||
}
|
||||
|
||||
advanceWidth := g.phantomPoints[1].X - g.phantomPoints[0].X
|
||||
if h != NoHinting {
|
||||
if len(f.hdmx) >= 8 {
|
||||
if n := u32(f.hdmx, 4); n > 3+uint32(i) {
|
||||
for hdmx := f.hdmx[8:]; uint32(len(hdmx)) >= n; hdmx = hdmx[n:] {
|
||||
if int32(hdmx[0]) == scale>>6 {
|
||||
advanceWidth = int32(hdmx[2+i]) << 6
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
advanceWidth = (advanceWidth + 32) &^ 63
|
||||
}
|
||||
g.AdvanceWidth = advanceWidth
|
||||
|
||||
// Set g.B to the 'control box', which is the bounding box of the Bézier
|
||||
// curves' control points. This is easier to calculate, no smaller than
|
||||
// and often equal to the tightest possible bounding box of the curves
|
||||
// themselves. This approach is what C Freetype does. We can't just scale
|
||||
// the nominal bounding box in the glyf data as the hinting process and
|
||||
// phantom point adjustment may move points outside of that box.
|
||||
if len(g.Point) == 0 {
|
||||
g.B = Bounds{}
|
||||
} else {
|
||||
p := g.Point[0]
|
||||
g.B.XMin = p.X
|
||||
g.B.XMax = p.X
|
||||
g.B.YMin = p.Y
|
||||
g.B.YMax = p.Y
|
||||
for _, p := range g.Point[1:] {
|
||||
if g.B.XMin > p.X {
|
||||
g.B.XMin = p.X
|
||||
} else if g.B.XMax < p.X {
|
||||
g.B.XMax = p.X
|
||||
}
|
||||
if g.B.YMin > p.Y {
|
||||
g.B.YMin = p.Y
|
||||
} else if g.B.YMax < p.Y {
|
||||
g.B.YMax = p.Y
|
||||
}
|
||||
}
|
||||
// Snap the box to the grid, if hinting is on.
|
||||
if h != NoHinting {
|
||||
g.B.XMin &^= 63
|
||||
g.B.YMin &^= 63
|
||||
g.B.XMax += 63
|
||||
g.B.XMax &^= 63
|
||||
g.B.YMax += 63
|
||||
g.B.YMax &^= 63
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GlyphBuf) load(recursion int32, i Index, useMyMetrics bool) (err error) {
|
||||
// The recursion limit here is arbitrary, but defends against malformed glyphs.
|
||||
if recursion >= 32 {
|
||||
return UnsupportedError("excessive compound glyph recursion")
|
||||
}
|
||||
// Find the relevant slice of g.font.glyf.
|
||||
var g0, g1 uint32
|
||||
if g.font.locaOffsetFormat == locaOffsetFormatShort {
|
||||
g0 = 2 * uint32(u16(g.font.loca, 2*int(i)))
|
||||
g1 = 2 * uint32(u16(g.font.loca, 2*int(i)+2))
|
||||
} else {
|
||||
g0 = u32(g.font.loca, 4*int(i))
|
||||
g1 = u32(g.font.loca, 4*int(i)+4)
|
||||
}
|
||||
|
||||
// Decode the contour count and nominal bounding box, from the first
|
||||
// 10 bytes of the glyf data. boundsYMin and boundsXMax, at offsets 4
|
||||
// and 6, are unused.
|
||||
glyf, ne, boundsXMin, boundsYMax := []byte(nil), 0, int32(0), int32(0)
|
||||
if g0+10 <= g1 {
|
||||
glyf = g.font.glyf[g0:g1]
|
||||
ne = int(int16(u16(glyf, 0)))
|
||||
boundsXMin = int32(int16(u16(glyf, 2)))
|
||||
boundsYMax = int32(int16(u16(glyf, 8)))
|
||||
}
|
||||
|
||||
// Create the phantom points.
|
||||
uhm, pp1x := g.font.unscaledHMetric(i), int32(0)
|
||||
uvm := g.font.unscaledVMetric(i, boundsYMax)
|
||||
g.phantomPoints = [4]Point{
|
||||
{X: boundsXMin - uhm.LeftSideBearing},
|
||||
{X: boundsXMin - uhm.LeftSideBearing + uhm.AdvanceWidth},
|
||||
{X: uhm.AdvanceWidth / 2, Y: boundsYMax + uvm.TopSideBearing},
|
||||
{X: uhm.AdvanceWidth / 2, Y: boundsYMax + uvm.TopSideBearing - uvm.AdvanceHeight},
|
||||
}
|
||||
if len(glyf) == 0 {
|
||||
g.addPhantomsAndScale(len(g.Point), len(g.Point), true, true)
|
||||
copy(g.phantomPoints[:], g.Point[len(g.Point)-4:])
|
||||
g.Point = g.Point[:len(g.Point)-4]
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load and hint the contours.
|
||||
if ne < 0 {
|
||||
if ne != -1 {
|
||||
// http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html says that
|
||||
// "the values -2, -3, and so forth, are reserved for future use."
|
||||
return UnsupportedError("negative number of contours")
|
||||
}
|
||||
pp1x = g.font.scale(g.scale * (boundsXMin - uhm.LeftSideBearing))
|
||||
if err := g.loadCompound(recursion, uhm, i, glyf, useMyMetrics); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
np0, ne0 := len(g.Point), len(g.End)
|
||||
program := g.loadSimple(glyf, ne)
|
||||
g.addPhantomsAndScale(np0, np0, true, true)
|
||||
pp1x = g.Point[len(g.Point)-4].X
|
||||
if g.hinting != NoHinting {
|
||||
if len(program) != 0 {
|
||||
err := g.hinter.run(
|
||||
program,
|
||||
g.Point[np0:],
|
||||
g.Unhinted[np0:],
|
||||
g.InFontUnits[np0:],
|
||||
g.End[ne0:],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// Drop the four phantom points.
|
||||
g.InFontUnits = g.InFontUnits[:len(g.InFontUnits)-4]
|
||||
g.Unhinted = g.Unhinted[:len(g.Unhinted)-4]
|
||||
}
|
||||
if useMyMetrics {
|
||||
copy(g.phantomPoints[:], g.Point[len(g.Point)-4:])
|
||||
}
|
||||
g.Point = g.Point[:len(g.Point)-4]
|
||||
if np0 != 0 {
|
||||
// The hinting program expects the []End values to be indexed relative
|
||||
// to the inner glyph, not the outer glyph, so we delay adding np0 until
|
||||
// after the hinting program (if any) has run.
|
||||
for i := ne0; i < len(g.End); i++ {
|
||||
g.End[i] += np0
|
||||
}
|
||||
}
|
||||
}
|
||||
if useMyMetrics && !g.metricsSet {
|
||||
g.metricsSet = true
|
||||
g.pp1x = pp1x
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadOffset is the initial offset for loadSimple and loadCompound. The first
|
||||
// 10 bytes are the number of contours and the bounding box.
|
||||
const loadOffset = 10
|
||||
|
||||
func (g *GlyphBuf) loadSimple(glyf []byte, ne int) (program []byte) {
|
||||
offset := loadOffset
|
||||
for i := 0; i < ne; i++ {
|
||||
g.End = append(g.End, 1+int(u16(glyf, offset)))
|
||||
offset += 2
|
||||
}
|
||||
|
||||
// Note the TrueType hinting instructions.
|
||||
instrLen := int(u16(glyf, offset))
|
||||
offset += 2
|
||||
program = glyf[offset : offset+instrLen]
|
||||
offset += instrLen
|
||||
|
||||
np0 := len(g.Point)
|
||||
np1 := np0 + int(g.End[len(g.End)-1])
|
||||
|
||||
// Decode the flags.
|
||||
for i := np0; i < np1; {
|
||||
c := uint32(glyf[offset])
|
||||
offset++
|
||||
g.Point = append(g.Point, Point{Flags: c})
|
||||
i++
|
||||
if c&flagRepeat != 0 {
|
||||
count := glyf[offset]
|
||||
offset++
|
||||
for ; count > 0; count-- {
|
||||
g.Point = append(g.Point, Point{Flags: c})
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decode the co-ordinates.
|
||||
var x int16
|
||||
for i := np0; i < np1; i++ {
|
||||
f := g.Point[i].Flags
|
||||
if f&flagXShortVector != 0 {
|
||||
dx := int16(glyf[offset])
|
||||
offset++
|
||||
if f&flagPositiveXShortVector == 0 {
|
||||
x -= dx
|
||||
} else {
|
||||
x += dx
|
||||
}
|
||||
} else if f&flagThisXIsSame == 0 {
|
||||
x += int16(u16(glyf, offset))
|
||||
offset += 2
|
||||
}
|
||||
g.Point[i].X = int32(x)
|
||||
}
|
||||
var y int16
|
||||
for i := np0; i < np1; i++ {
|
||||
f := g.Point[i].Flags
|
||||
if f&flagYShortVector != 0 {
|
||||
dy := int16(glyf[offset])
|
||||
offset++
|
||||
if f&flagPositiveYShortVector == 0 {
|
||||
y -= dy
|
||||
} else {
|
||||
y += dy
|
||||
}
|
||||
} else if f&flagThisYIsSame == 0 {
|
||||
y += int16(u16(glyf, offset))
|
||||
offset += 2
|
||||
}
|
||||
g.Point[i].Y = int32(y)
|
||||
}
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
func (g *GlyphBuf) loadCompound(recursion int32, uhm HMetric, i Index,
|
||||
glyf []byte, useMyMetrics bool) error {
|
||||
|
||||
// Flags for decoding a compound glyph. These flags are documented at
|
||||
// http://developer.apple.com/fonts/TTRefMan/RM06/Chap6glyf.html.
|
||||
const (
|
||||
flagArg1And2AreWords = 1 << iota
|
||||
flagArgsAreXYValues
|
||||
flagRoundXYToGrid
|
||||
flagWeHaveAScale
|
||||
flagUnused
|
||||
flagMoreComponents
|
||||
flagWeHaveAnXAndYScale
|
||||
flagWeHaveATwoByTwo
|
||||
flagWeHaveInstructions
|
||||
flagUseMyMetrics
|
||||
flagOverlapCompound
|
||||
)
|
||||
np0, ne0 := len(g.Point), len(g.End)
|
||||
offset := loadOffset
|
||||
for {
|
||||
flags := u16(glyf, offset)
|
||||
component := Index(u16(glyf, offset+2))
|
||||
dx, dy, transform, hasTransform := int32(0), int32(0), [4]int32{}, false
|
||||
if flags&flagArg1And2AreWords != 0 {
|
||||
dx = int32(int16(u16(glyf, offset+4)))
|
||||
dy = int32(int16(u16(glyf, offset+6)))
|
||||
offset += 8
|
||||
} else {
|
||||
dx = int32(int16(int8(glyf[offset+4])))
|
||||
dy = int32(int16(int8(glyf[offset+5])))
|
||||
offset += 6
|
||||
}
|
||||
if flags&flagArgsAreXYValues == 0 {
|
||||
return UnsupportedError("compound glyph transform vector")
|
||||
}
|
||||
if flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0 {
|
||||
hasTransform = true
|
||||
switch {
|
||||
case flags&flagWeHaveAScale != 0:
|
||||
transform[0] = int32(int16(u16(glyf, offset+0)))
|
||||
transform[3] = transform[0]
|
||||
offset += 2
|
||||
case flags&flagWeHaveAnXAndYScale != 0:
|
||||
transform[0] = int32(int16(u16(glyf, offset+0)))
|
||||
transform[3] = int32(int16(u16(glyf, offset+2)))
|
||||
offset += 4
|
||||
case flags&flagWeHaveATwoByTwo != 0:
|
||||
transform[0] = int32(int16(u16(glyf, offset+0)))
|
||||
transform[1] = int32(int16(u16(glyf, offset+2)))
|
||||
transform[2] = int32(int16(u16(glyf, offset+4)))
|
||||
transform[3] = int32(int16(u16(glyf, offset+6)))
|
||||
offset += 8
|
||||
}
|
||||
}
|
||||
savedPP := g.phantomPoints
|
||||
np0 := len(g.Point)
|
||||
componentUMM := useMyMetrics && (flags&flagUseMyMetrics != 0)
|
||||
if err := g.load(recursion+1, component, componentUMM); err != nil {
|
||||
return err
|
||||
}
|
||||
if flags&flagUseMyMetrics == 0 {
|
||||
g.phantomPoints = savedPP
|
||||
}
|
||||
if hasTransform {
|
||||
for j := np0; j < len(g.Point); j++ {
|
||||
p := &g.Point[j]
|
||||
newX := int32((int64(p.X)*int64(transform[0])+1<<13)>>14) +
|
||||
int32((int64(p.Y)*int64(transform[2])+1<<13)>>14)
|
||||
newY := int32((int64(p.X)*int64(transform[1])+1<<13)>>14) +
|
||||
int32((int64(p.Y)*int64(transform[3])+1<<13)>>14)
|
||||
p.X, p.Y = newX, newY
|
||||
}
|
||||
}
|
||||
dx = g.font.scale(g.scale * dx)
|
||||
dy = g.font.scale(g.scale * dy)
|
||||
if flags&flagRoundXYToGrid != 0 {
|
||||
dx = (dx + 32) &^ 63
|
||||
dy = (dy + 32) &^ 63
|
||||
}
|
||||
for j := np0; j < len(g.Point); j++ {
|
||||
p := &g.Point[j]
|
||||
p.X += dx
|
||||
p.Y += dy
|
||||
}
|
||||
// TODO: also adjust g.InFontUnits and g.Unhinted?
|
||||
if flags&flagMoreComponents == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
instrLen := 0
|
||||
if g.hinting != NoHinting && offset+2 <= len(glyf) {
|
||||
instrLen = int(u16(glyf, offset))
|
||||
offset += 2
|
||||
}
|
||||
|
||||
g.addPhantomsAndScale(np0, len(g.Point), false, instrLen > 0)
|
||||
points, ends := g.Point[np0:], g.End[ne0:]
|
||||
g.Point = g.Point[:len(g.Point)-4]
|
||||
for j := range points {
|
||||
points[j].Flags &^= flagTouchedX | flagTouchedY
|
||||
}
|
||||
|
||||
if instrLen == 0 {
|
||||
if !g.metricsSet {
|
||||
copy(g.phantomPoints[:], points[len(points)-4:])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hint the compound glyph.
|
||||
program := glyf[offset : offset+instrLen]
|
||||
// Temporarily adjust the ends to be relative to this compound glyph.
|
||||
if np0 != 0 {
|
||||
for i := range ends {
|
||||
ends[i] -= np0
|
||||
}
|
||||
}
|
||||
// Hinting instructions of a composite glyph completely refer to the
|
||||
// (already) hinted subglyphs.
|
||||
g.tmp = append(g.tmp[:0], points...)
|
||||
if err := g.hinter.run(program, points, g.tmp, g.tmp, ends); err != nil {
|
||||
return err
|
||||
}
|
||||
if np0 != 0 {
|
||||
for i := range ends {
|
||||
ends[i] += np0
|
||||
}
|
||||
}
|
||||
if !g.metricsSet {
|
||||
copy(g.phantomPoints[:], points[len(points)-4:])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GlyphBuf) addPhantomsAndScale(np0, np1 int, simple, adjust bool) {
|
||||
// Add the four phantom points.
|
||||
g.Point = append(g.Point, g.phantomPoints[:]...)
|
||||
// Scale the points.
|
||||
if simple && g.hinting != NoHinting {
|
||||
g.InFontUnits = append(g.InFontUnits, g.Point[np1:]...)
|
||||
}
|
||||
for i := np1; i < len(g.Point); i++ {
|
||||
p := &g.Point[i]
|
||||
p.X = g.font.scale(g.scale * p.X)
|
||||
p.Y = g.font.scale(g.scale * p.Y)
|
||||
}
|
||||
if g.hinting == NoHinting {
|
||||
return
|
||||
}
|
||||
// Round the 1st phantom point to the grid, shifting all other points equally.
|
||||
// Note that "all other points" starts from np0, not np1.
|
||||
// TODO: delete this adjustment and the np0/np1 distinction, when
|
||||
// we update the compatibility tests to C Freetype 2.5.3.
|
||||
// See http://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=05c786d990390a7ca18e62962641dac740bacb06
|
||||
if adjust {
|
||||
pp1x := g.Point[len(g.Point)-4].X
|
||||
if dx := ((pp1x + 32) &^ 63) - pp1x; dx != 0 {
|
||||
for i := np0; i < len(g.Point); i++ {
|
||||
g.Point[i].X += dx
|
||||
}
|
||||
}
|
||||
}
|
||||
if simple {
|
||||
g.Unhinted = append(g.Unhinted, g.Point[np1:]...)
|
||||
}
|
||||
// Round the 2nd and 4th phantom point to the grid.
|
||||
p := &g.Point[len(g.Point)-3]
|
||||
p.X = (p.X + 32) &^ 63
|
||||
p = &g.Point[len(g.Point)-1]
|
||||
p.Y = (p.Y + 32) &^ 63
|
||||
}
|
||||
|
||||
// TODO: is this necessary? The zero-valued GlyphBuf is perfectly usable.
|
||||
|
||||
// NewGlyphBuf returns a newly allocated GlyphBuf.
|
||||
func NewGlyphBuf() *GlyphBuf {
|
||||
return &GlyphBuf{
|
||||
Point: make([]Point, 0, 256),
|
||||
End: make([]int, 0, 32),
|
||||
}
|
||||
}
|
||||
1764
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/hint.go
сгенерированный
поставляемый
1764
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/hint.go
сгенерированный
поставляемый
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
673
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/hint_test.go
сгенерированный
поставляемый
673
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/hint_test.go
сгенерированный
поставляемый
@@ -1,673 +0,0 @@
|
||||
// Copyright 2012 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package truetype
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBytecode(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
prog []byte
|
||||
want []int32
|
||||
errStr string
|
||||
}{
|
||||
{
|
||||
"underflow",
|
||||
[]byte{
|
||||
opDUP,
|
||||
},
|
||||
nil,
|
||||
"underflow",
|
||||
},
|
||||
{
|
||||
"infinite loop",
|
||||
[]byte{
|
||||
opPUSHW000, // [-1]
|
||||
0xff,
|
||||
0xff,
|
||||
opDUP, // [-1, -1]
|
||||
opJMPR, // [-1]
|
||||
},
|
||||
nil,
|
||||
"too many steps",
|
||||
},
|
||||
{
|
||||
"unbalanced if/else",
|
||||
[]byte{
|
||||
opPUSHB000, // [0]
|
||||
0,
|
||||
opIF,
|
||||
},
|
||||
nil,
|
||||
"unbalanced",
|
||||
},
|
||||
{
|
||||
"vector set/gets",
|
||||
[]byte{
|
||||
opSVTCA1, // []
|
||||
opGPV, // [0x4000, 0]
|
||||
opSVTCA0, // [0x4000, 0]
|
||||
opGFV, // [0x4000, 0, 0, 0x4000]
|
||||
opNEG, // [0x4000, 0, 0, -0x4000]
|
||||
opSPVFS, // [0x4000, 0]
|
||||
opSFVTPV, // [0x4000, 0]
|
||||
opPUSHB000, // [0x4000, 0, 1]
|
||||
1,
|
||||
opGFV, // [0x4000, 0, 1, 0, -0x4000]
|
||||
opPUSHB000, // [0x4000, 0, 1, 0, -0x4000, 2]
|
||||
2,
|
||||
},
|
||||
[]int32{0x4000, 0, 1, 0, -0x4000, 2},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"jumps",
|
||||
[]byte{
|
||||
opPUSHB001, // [10, 2]
|
||||
10,
|
||||
2,
|
||||
opJMPR, // [10]
|
||||
opDUP, // not executed
|
||||
opDUP, // [10, 10]
|
||||
opPUSHB010, // [10, 10, 20, 2, 1]
|
||||
20,
|
||||
2,
|
||||
1,
|
||||
opJROT, // [10, 10, 20]
|
||||
opDUP, // not executed
|
||||
opDUP, // [10, 10, 20, 20]
|
||||
opPUSHB010, // [10, 10, 20, 20, 30, 2, 1]
|
||||
30,
|
||||
2,
|
||||
1,
|
||||
opJROF, // [10, 10, 20, 20, 30]
|
||||
opDUP, // [10, 10, 20, 20, 30, 30]
|
||||
opDUP, // [10, 10, 20, 20, 30, 30, 30]
|
||||
},
|
||||
[]int32{10, 10, 20, 20, 30, 30, 30},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"stack ops",
|
||||
[]byte{
|
||||
opPUSHB010, // [10, 20, 30]
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
opCLEAR, // []
|
||||
opPUSHB010, // [40, 50, 60]
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
opSWAP, // [40, 60, 50]
|
||||
opDUP, // [40, 60, 50, 50]
|
||||
opDUP, // [40, 60, 50, 50, 50]
|
||||
opPOP, // [40, 60, 50, 50]
|
||||
opDEPTH, // [40, 60, 50, 50, 4]
|
||||
opCINDEX, // [40, 60, 50, 50, 40]
|
||||
opPUSHB000, // [40, 60, 50, 50, 40, 4]
|
||||
4,
|
||||
opMINDEX, // [40, 50, 50, 40, 60]
|
||||
},
|
||||
[]int32{40, 50, 50, 40, 60},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"push ops",
|
||||
[]byte{
|
||||
opPUSHB000, // [255]
|
||||
255,
|
||||
opPUSHW001, // [255, -2, 253]
|
||||
255,
|
||||
254,
|
||||
0,
|
||||
253,
|
||||
opNPUSHB, // [1, -2, 253, 1, 2]
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
opNPUSHW, // [1, -2, 253, 1, 2, 0x0405, 0x0607, 0x0809]
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
},
|
||||
[]int32{255, -2, 253, 1, 2, 0x0405, 0x0607, 0x0809},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"store ops",
|
||||
[]byte{
|
||||
opPUSHB011, // [1, 22, 3, 44]
|
||||
1,
|
||||
22,
|
||||
3,
|
||||
44,
|
||||
opWS, // [1, 22]
|
||||
opWS, // []
|
||||
opPUSHB000, // [3]
|
||||
3,
|
||||
opRS, // [44]
|
||||
},
|
||||
[]int32{44},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"comparison ops",
|
||||
[]byte{
|
||||
opPUSHB001, // [10, 20]
|
||||
10,
|
||||
20,
|
||||
opLT, // [1]
|
||||
opPUSHB001, // [1, 10, 20]
|
||||
10,
|
||||
20,
|
||||
opLTEQ, // [1, 1]
|
||||
opPUSHB001, // [1, 1, 10, 20]
|
||||
10,
|
||||
20,
|
||||
opGT, // [1, 1, 0]
|
||||
opPUSHB001, // [1, 1, 0, 10, 20]
|
||||
10,
|
||||
20,
|
||||
opGTEQ, // [1, 1, 0, 0]
|
||||
opEQ, // [1, 1, 1]
|
||||
opNEQ, // [1, 0]
|
||||
},
|
||||
[]int32{1, 0},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"odd/even",
|
||||
// Calculate odd(2+31/64), odd(2+32/64), even(2), even(1).
|
||||
[]byte{
|
||||
opPUSHB000, // [159]
|
||||
159,
|
||||
opODD, // [0]
|
||||
opPUSHB000, // [0, 160]
|
||||
160,
|
||||
opODD, // [0, 1]
|
||||
opPUSHB000, // [0, 1, 128]
|
||||
128,
|
||||
opEVEN, // [0, 1, 1]
|
||||
opPUSHB000, // [0, 1, 1, 64]
|
||||
64,
|
||||
opEVEN, // [0, 1, 1, 0]
|
||||
},
|
||||
[]int32{0, 1, 1, 0},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"if true",
|
||||
[]byte{
|
||||
opPUSHB001, // [255, 1]
|
||||
255,
|
||||
1,
|
||||
opIF,
|
||||
opPUSHB000, // [255, 2]
|
||||
2,
|
||||
opEIF,
|
||||
opPUSHB000, // [255, 2, 254]
|
||||
254,
|
||||
},
|
||||
[]int32{255, 2, 254},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"if false",
|
||||
[]byte{
|
||||
opPUSHB001, // [255, 0]
|
||||
255,
|
||||
0,
|
||||
opIF,
|
||||
opPUSHB000, // [255]
|
||||
2,
|
||||
opEIF,
|
||||
opPUSHB000, // [255, 254]
|
||||
254,
|
||||
},
|
||||
[]int32{255, 254},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"if/else true",
|
||||
[]byte{
|
||||
opPUSHB000, // [1]
|
||||
1,
|
||||
opIF,
|
||||
opPUSHB000, // [2]
|
||||
2,
|
||||
opELSE,
|
||||
opPUSHB000, // not executed
|
||||
3,
|
||||
opEIF,
|
||||
},
|
||||
[]int32{2},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"if/else false",
|
||||
[]byte{
|
||||
opPUSHB000, // [0]
|
||||
0,
|
||||
opIF,
|
||||
opPUSHB000, // not executed
|
||||
2,
|
||||
opELSE,
|
||||
opPUSHB000, // [3]
|
||||
3,
|
||||
opEIF,
|
||||
},
|
||||
[]int32{3},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"if/else true if/else false",
|
||||
// 0x58 is the opcode for opIF. The literal 0x58s below are pushed data.
|
||||
[]byte{
|
||||
opPUSHB010, // [255, 0, 1]
|
||||
255,
|
||||
0,
|
||||
1,
|
||||
opIF,
|
||||
opIF,
|
||||
opPUSHB001, // not executed
|
||||
0x58,
|
||||
0x58,
|
||||
opELSE,
|
||||
opPUSHW000, // [255, 0x5858]
|
||||
0x58,
|
||||
0x58,
|
||||
opEIF,
|
||||
opELSE,
|
||||
opIF,
|
||||
opNPUSHB, // not executed
|
||||
3,
|
||||
0x58,
|
||||
0x58,
|
||||
0x58,
|
||||
opELSE,
|
||||
opNPUSHW, // not executed
|
||||
2,
|
||||
0x58,
|
||||
0x58,
|
||||
0x58,
|
||||
0x58,
|
||||
opEIF,
|
||||
opEIF,
|
||||
opPUSHB000, // [255, 0x5858, 254]
|
||||
254,
|
||||
},
|
||||
[]int32{255, 0x5858, 254},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"if/else false if/else true",
|
||||
// 0x58 is the opcode for opIF. The literal 0x58s below are pushed data.
|
||||
[]byte{
|
||||
opPUSHB010, // [255, 1, 0]
|
||||
255,
|
||||
1,
|
||||
0,
|
||||
opIF,
|
||||
opIF,
|
||||
opPUSHB001, // not executed
|
||||
0x58,
|
||||
0x58,
|
||||
opELSE,
|
||||
opPUSHW000, // not executed
|
||||
0x58,
|
||||
0x58,
|
||||
opEIF,
|
||||
opELSE,
|
||||
opIF,
|
||||
opNPUSHB, // [255, 0x58, 0x58, 0x58]
|
||||
3,
|
||||
0x58,
|
||||
0x58,
|
||||
0x58,
|
||||
opELSE,
|
||||
opNPUSHW, // not executed
|
||||
2,
|
||||
0x58,
|
||||
0x58,
|
||||
0x58,
|
||||
0x58,
|
||||
opEIF,
|
||||
opEIF,
|
||||
opPUSHB000, // [255, 0x58, 0x58, 0x58, 254]
|
||||
254,
|
||||
},
|
||||
[]int32{255, 0x58, 0x58, 0x58, 254},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"logical ops",
|
||||
[]byte{
|
||||
opPUSHB010, // [0, 10, 20]
|
||||
0,
|
||||
10,
|
||||
20,
|
||||
opAND, // [0, 1]
|
||||
opOR, // [1]
|
||||
opNOT, // [0]
|
||||
},
|
||||
[]int32{0},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"arithmetic ops",
|
||||
// Calculate abs((-(1 - (2*3)))/2 + 1/64).
|
||||
// The answer is 5/2 + 1/64 in ideal numbers, or 161 in 26.6 fixed point math.
|
||||
[]byte{
|
||||
opPUSHB010, // [64, 128, 192]
|
||||
1 << 6,
|
||||
2 << 6,
|
||||
3 << 6,
|
||||
opMUL, // [64, 384]
|
||||
opSUB, // [-320]
|
||||
opNEG, // [320]
|
||||
opPUSHB000, // [320, 128]
|
||||
2 << 6,
|
||||
opDIV, // [160]
|
||||
opPUSHB000, // [160, 1]
|
||||
1,
|
||||
opADD, // [161]
|
||||
opABS, // [161]
|
||||
},
|
||||
[]int32{161},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"floor, ceiling",
|
||||
[]byte{
|
||||
opPUSHB000, // [96]
|
||||
96,
|
||||
opFLOOR, // [64]
|
||||
opPUSHB000, // [64, 96]
|
||||
96,
|
||||
opCEILING, // [64, 128]
|
||||
},
|
||||
[]int32{64, 128},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"rounding",
|
||||
// Round 1.40625 (which is 90/64) under various rounding policies.
|
||||
// See figure 20 of https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding
|
||||
[]byte{
|
||||
opROFF, // []
|
||||
opPUSHB000, // [90]
|
||||
90,
|
||||
opROUND00, // [90]
|
||||
opRTG, // [90]
|
||||
opPUSHB000, // [90, 90]
|
||||
90,
|
||||
opROUND00, // [90, 64]
|
||||
opRTHG, // [90, 64]
|
||||
opPUSHB000, // [90, 64, 90]
|
||||
90,
|
||||
opROUND00, // [90, 64, 96]
|
||||
opRDTG, // [90, 64, 96]
|
||||
opPUSHB000, // [90, 64, 96, 90]
|
||||
90,
|
||||
opROUND00, // [90, 64, 96, 64]
|
||||
opRUTG, // [90, 64, 96, 64]
|
||||
opPUSHB000, // [90, 64, 96, 64, 90]
|
||||
90,
|
||||
opROUND00, // [90, 64, 96, 64, 128]
|
||||
opRTDG, // [90, 64, 96, 64, 128]
|
||||
opPUSHB000, // [90, 64, 96, 64, 128, 90]
|
||||
90,
|
||||
opROUND00, // [90, 64, 96, 64, 128, 96]
|
||||
},
|
||||
[]int32{90, 64, 96, 64, 128, 96},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"super-rounding",
|
||||
// See figure 20 of https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding
|
||||
// and the sign preservation steps of the "Order of rounding operations" section.
|
||||
[]byte{
|
||||
opPUSHB000, // [0x58]
|
||||
0x58,
|
||||
opSROUND, // []
|
||||
opPUSHW000, // [-81]
|
||||
0xff,
|
||||
0xaf,
|
||||
opROUND00, // [-80]
|
||||
opPUSHW000, // [-80, -80]
|
||||
0xff,
|
||||
0xb0,
|
||||
opROUND00, // [-80, -80]
|
||||
opPUSHW000, // [-80, -80, -17]
|
||||
0xff,
|
||||
0xef,
|
||||
opROUND00, // [-80, -80, -16]
|
||||
opPUSHW000, // [-80, -80, -16, -16]
|
||||
0xff,
|
||||
0xf0,
|
||||
opROUND00, // [-80, -80, -16, -16]
|
||||
opPUSHB000, // [-80, -80, -16, -16, 0]
|
||||
0,
|
||||
opROUND00, // [-80, -80, -16, -16, 16]
|
||||
opPUSHB000, // [-80, -80, -16, -16, 16, 16]
|
||||
16,
|
||||
opROUND00, // [-80, -80, -16, -16, 16, 16]
|
||||
opPUSHB000, // [-80, -80, -16, -16, 16, 16, 47]
|
||||
47,
|
||||
opROUND00, // [-80, -80, -16, -16, 16, 16, 16]
|
||||
opPUSHB000, // [-80, -80, -16, -16, 16, 16, 16, 48]
|
||||
48,
|
||||
opROUND00, // [-80, -80, -16, -16, 16, 16, 16, 80]
|
||||
},
|
||||
[]int32{-80, -80, -16, -16, 16, 16, 16, 80},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"roll",
|
||||
[]byte{
|
||||
opPUSHB010, // [1, 2, 3]
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
opROLL, // [2, 3, 1]
|
||||
},
|
||||
[]int32{2, 3, 1},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"max/min",
|
||||
[]byte{
|
||||
opPUSHW001, // [-2, -3]
|
||||
0xff,
|
||||
0xfe,
|
||||
0xff,
|
||||
0xfd,
|
||||
opMAX, // [-2]
|
||||
opPUSHW001, // [-2, -4, -5]
|
||||
0xff,
|
||||
0xfc,
|
||||
0xff,
|
||||
0xfb,
|
||||
opMIN, // [-2, -5]
|
||||
},
|
||||
[]int32{-2, -5},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"functions",
|
||||
[]byte{
|
||||
opPUSHB011, // [3, 7, 0, 3]
|
||||
3,
|
||||
7,
|
||||
0,
|
||||
3,
|
||||
|
||||
opFDEF, // Function #3 (not called)
|
||||
opPUSHB000,
|
||||
98,
|
||||
opENDF,
|
||||
|
||||
opFDEF, // Function #0
|
||||
opDUP,
|
||||
opADD,
|
||||
opENDF,
|
||||
|
||||
opFDEF, // Function #7
|
||||
opPUSHB001,
|
||||
10,
|
||||
0,
|
||||
opCALL,
|
||||
opDUP,
|
||||
opENDF,
|
||||
|
||||
opFDEF, // Function #3 (again)
|
||||
opPUSHB000,
|
||||
99,
|
||||
opENDF,
|
||||
|
||||
opPUSHB001, // [2, 0]
|
||||
2,
|
||||
0,
|
||||
opCALL, // [4]
|
||||
opPUSHB000, // [4, 3]
|
||||
3,
|
||||
opLOOPCALL, // [99, 99, 99, 99]
|
||||
opPUSHB000, // [99, 99, 99, 99, 7]
|
||||
7,
|
||||
opCALL, // [99, 99, 99, 99, 20, 20]
|
||||
},
|
||||
[]int32{99, 99, 99, 99, 20, 20},
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
h := &hinter{}
|
||||
h.init(&Font{
|
||||
maxStorage: 32,
|
||||
maxStackElements: 100,
|
||||
}, 768)
|
||||
err, errStr := h.run(tc.prog, nil, nil, nil, nil), ""
|
||||
if err != nil {
|
||||
errStr = err.Error()
|
||||
}
|
||||
if tc.errStr != "" {
|
||||
if errStr == "" {
|
||||
t.Errorf("%s: got no error, want %q", tc.desc, tc.errStr)
|
||||
} else if !strings.Contains(errStr, tc.errStr) {
|
||||
t.Errorf("%s: got error %q, want one containing %q", tc.desc, errStr, tc.errStr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if errStr != "" {
|
||||
t.Errorf("%s: got error %q, want none", tc.desc, errStr)
|
||||
continue
|
||||
}
|
||||
got := h.stack[:len(tc.want)]
|
||||
if !reflect.DeepEqual(got, tc.want) {
|
||||
t.Errorf("%s: got %v, want %v", tc.desc, got, tc.want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMove tests that the hinter.move method matches the output of the C
|
||||
// Freetype implementation.
|
||||
func TestMove(t *testing.T) {
|
||||
h, p := hinter{}, Point{}
|
||||
testCases := []struct {
|
||||
pvX, pvY, fvX, fvY f2dot14
|
||||
wantX, wantY int32
|
||||
}{
|
||||
{+0x4000, +0x0000, +0x4000, +0x0000, +1000, +0},
|
||||
{+0x4000, +0x0000, -0x4000, +0x0000, +1000, +0},
|
||||
{-0x4000, +0x0000, +0x4000, +0x0000, -1000, +0},
|
||||
{-0x4000, +0x0000, -0x4000, +0x0000, -1000, +0},
|
||||
{+0x0000, +0x4000, +0x0000, +0x4000, +0, +1000},
|
||||
{+0x0000, +0x4000, +0x0000, -0x4000, +0, +1000},
|
||||
{+0x4000, +0x0000, +0x2d41, +0x2d41, +1000, +1000},
|
||||
{+0x4000, +0x0000, -0x2d41, +0x2d41, +1000, -1000},
|
||||
{+0x4000, +0x0000, +0x2d41, -0x2d41, +1000, -1000},
|
||||
{+0x4000, +0x0000, -0x2d41, -0x2d41, +1000, +1000},
|
||||
{-0x4000, +0x0000, +0x2d41, +0x2d41, -1000, -1000},
|
||||
{-0x4000, +0x0000, -0x2d41, +0x2d41, -1000, +1000},
|
||||
{-0x4000, +0x0000, +0x2d41, -0x2d41, -1000, +1000},
|
||||
{-0x4000, +0x0000, -0x2d41, -0x2d41, -1000, -1000},
|
||||
{+0x376d, +0x2000, +0x2d41, +0x2d41, +732, +732},
|
||||
{-0x376d, +0x2000, +0x2d41, +0x2d41, -2732, -2732},
|
||||
{+0x376d, +0x2000, +0x2d41, -0x2d41, +2732, -2732},
|
||||
{-0x376d, +0x2000, +0x2d41, -0x2d41, -732, +732},
|
||||
{-0x376d, -0x2000, +0x2d41, +0x2d41, -732, -732},
|
||||
{+0x376d, +0x2000, +0x4000, +0x0000, +1155, +0},
|
||||
{+0x376d, +0x2000, +0x0000, +0x4000, +0, +2000},
|
||||
}
|
||||
for _, tc := range testCases {
|
||||
p = Point{}
|
||||
h.gs.pv = [2]f2dot14{tc.pvX, tc.pvY}
|
||||
h.gs.fv = [2]f2dot14{tc.fvX, tc.fvY}
|
||||
h.move(&p, 1000, true)
|
||||
tx := p.Flags&flagTouchedX != 0
|
||||
ty := p.Flags&flagTouchedY != 0
|
||||
wantTX := tc.fvX != 0
|
||||
wantTY := tc.fvY != 0
|
||||
if p.X != tc.wantX || p.Y != tc.wantY || tx != wantTX || ty != wantTY {
|
||||
t.Errorf("pv=%v, fv=%v\ngot %d, %d, %t, %t\nwant %d, %d, %t, %t",
|
||||
h.gs.pv, h.gs.fv, p.X, p.Y, tx, ty, tc.wantX, tc.wantY, wantTX, wantTY)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check that p is aligned with the freedom vector.
|
||||
a := int64(p.X) * int64(tc.fvY)
|
||||
b := int64(p.Y) * int64(tc.fvX)
|
||||
if a != b {
|
||||
t.Errorf("pv=%v, fv=%v, p=%v not aligned with fv", h.gs.pv, h.gs.fv, p)
|
||||
continue
|
||||
}
|
||||
|
||||
// Check that the projected p is 1000 away from the origin.
|
||||
dotProd := (int64(p.X)*int64(tc.pvX) + int64(p.Y)*int64(tc.pvY) + 1<<13) >> 14
|
||||
if dotProd != 1000 {
|
||||
t.Errorf("pv=%v, fv=%v, p=%v not 1000 from origin", h.gs.pv, h.gs.fv, p)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalize tests that the normalize function matches the output of the C
|
||||
// Freetype implementation.
|
||||
func TestNormalize(t *testing.T) {
|
||||
testCases := [][2]f2dot14{
|
||||
{-15895, 3974},
|
||||
{-15543, 5181},
|
||||
{-14654, 7327},
|
||||
{-11585, 11585},
|
||||
{0, 16384},
|
||||
{11585, 11585},
|
||||
{14654, 7327},
|
||||
{15543, 5181},
|
||||
{15895, 3974},
|
||||
{16066, 3213},
|
||||
{16161, 2694},
|
||||
{16219, 2317},
|
||||
{16257, 2032},
|
||||
{16284, 1809},
|
||||
}
|
||||
for i, want := range testCases {
|
||||
got := normalize(f2dot14(i)-4, 1)
|
||||
if got != want {
|
||||
t.Errorf("i=%d: got %v, want %v", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
289
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/opcodes.go
сгенерированный
поставляемый
289
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/opcodes.go
сгенерированный
поставляемый
@@ -1,289 +0,0 @@
|
||||
// Copyright 2012 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package truetype
|
||||
|
||||
// The Truetype opcodes are summarized at
|
||||
// https://developer.apple.com/fonts/TTRefMan/RM07/appendixA.html
|
||||
|
||||
const (
|
||||
opSVTCA0 = 0x00 // Set freedom and projection Vectors To Coordinate Axis
|
||||
opSVTCA1 = 0x01 // .
|
||||
opSPVTCA0 = 0x02 // Set Projection Vector To Coordinate Axis
|
||||
opSPVTCA1 = 0x03 // .
|
||||
opSFVTCA0 = 0x04 // Set Freedom Vector to Coordinate Axis
|
||||
opSFVTCA1 = 0x05 // .
|
||||
opSPVTL0 = 0x06 // Set Projection Vector To Line
|
||||
opSPVTL1 = 0x07 // .
|
||||
opSFVTL0 = 0x08 // Set Freedom Vector To Line
|
||||
opSFVTL1 = 0x09 // .
|
||||
opSPVFS = 0x0a // Set Projection Vector From Stack
|
||||
opSFVFS = 0x0b // Set Freedom Vector From Stack
|
||||
opGPV = 0x0c // Get Projection Vector
|
||||
opGFV = 0x0d // Get Freedom Vector
|
||||
opSFVTPV = 0x0e // Set Freedom Vector To Projection Vector
|
||||
opISECT = 0x0f // moves point p to the InterSECTion of two lines
|
||||
opSRP0 = 0x10 // Set Reference Point 0
|
||||
opSRP1 = 0x11 // Set Reference Point 1
|
||||
opSRP2 = 0x12 // Set Reference Point 2
|
||||
opSZP0 = 0x13 // Set Zone Pointer 0
|
||||
opSZP1 = 0x14 // Set Zone Pointer 1
|
||||
opSZP2 = 0x15 // Set Zone Pointer 2
|
||||
opSZPS = 0x16 // Set Zone PointerS
|
||||
opSLOOP = 0x17 // Set LOOP variable
|
||||
opRTG = 0x18 // Round To Grid
|
||||
opRTHG = 0x19 // Round To Half Grid
|
||||
opSMD = 0x1a // Set Minimum Distance
|
||||
opELSE = 0x1b // ELSE clause
|
||||
opJMPR = 0x1c // JuMP Relative
|
||||
opSCVTCI = 0x1d // Set Control Value Table Cut-In
|
||||
opSSWCI = 0x1e // Set Single Width Cut-In
|
||||
opSSW = 0x1f // Set Single Width
|
||||
opDUP = 0x20 // DUPlicate top stack element
|
||||
opPOP = 0x21 // POP top stack element
|
||||
opCLEAR = 0x22 // CLEAR the stack
|
||||
opSWAP = 0x23 // SWAP the top two elements on the stack
|
||||
opDEPTH = 0x24 // DEPTH of the stack
|
||||
opCINDEX = 0x25 // Copy the INDEXed element to the top of the stack
|
||||
opMINDEX = 0x26 // Move the INDEXed element to the top of the stack
|
||||
opALIGNPTS = 0x27 // ALIGN PoinTS
|
||||
op_0x28 = 0x28 // deprecated
|
||||
opUTP = 0x29 // UnTouch Point
|
||||
opLOOPCALL = 0x2a // LOOP and CALL function
|
||||
opCALL = 0x2b // CALL function
|
||||
opFDEF = 0x2c // Function DEFinition
|
||||
opENDF = 0x2d // END Function definition
|
||||
opMDAP0 = 0x2e // Move Direct Absolute Point
|
||||
opMDAP1 = 0x2f // .
|
||||
opIUP0 = 0x30 // Interpolate Untouched Points through the outline
|
||||
opIUP1 = 0x31 // .
|
||||
opSHP0 = 0x32 // SHift Point using reference point
|
||||
opSHP1 = 0x33 // .
|
||||
opSHC0 = 0x34 // SHift Contour using reference point
|
||||
opSHC1 = 0x35 // .
|
||||
opSHZ0 = 0x36 // SHift Zone using reference point
|
||||
opSHZ1 = 0x37 // .
|
||||
opSHPIX = 0x38 // SHift point by a PIXel amount
|
||||
opIP = 0x39 // Interpolate Point
|
||||
opMSIRP0 = 0x3a // Move Stack Indirect Relative Point
|
||||
opMSIRP1 = 0x3b // .
|
||||
opALIGNRP = 0x3c // ALIGN to Reference Point
|
||||
opRTDG = 0x3d // Round To Double Grid
|
||||
opMIAP0 = 0x3e // Move Indirect Absolute Point
|
||||
opMIAP1 = 0x3f // .
|
||||
opNPUSHB = 0x40 // PUSH N Bytes
|
||||
opNPUSHW = 0x41 // PUSH N Words
|
||||
opWS = 0x42 // Write Store
|
||||
opRS = 0x43 // Read Store
|
||||
opWCVTP = 0x44 // Write Control Value Table in Pixel units
|
||||
opRCVT = 0x45 // Read Control Value Table entry
|
||||
opGC0 = 0x46 // Get Coordinate projected onto the projection vector
|
||||
opGC1 = 0x47 // .
|
||||
opSCFS = 0x48 // Sets Coordinate From the Stack using projection vector and freedom vector
|
||||
opMD0 = 0x49 // Measure Distance
|
||||
opMD1 = 0x4a // .
|
||||
opMPPEM = 0x4b // Measure Pixels Per EM
|
||||
opMPS = 0x4c // Measure Point Size
|
||||
opFLIPON = 0x4d // set the auto FLIP Boolean to ON
|
||||
opFLIPOFF = 0x4e // set the auto FLIP Boolean to OFF
|
||||
opDEBUG = 0x4f // DEBUG call
|
||||
opLT = 0x50 // Less Than
|
||||
opLTEQ = 0x51 // Less Than or EQual
|
||||
opGT = 0x52 // Greater Than
|
||||
opGTEQ = 0x53 // Greater Than or EQual
|
||||
opEQ = 0x54 // EQual
|
||||
opNEQ = 0x55 // Not EQual
|
||||
opODD = 0x56 // ODD
|
||||
opEVEN = 0x57 // EVEN
|
||||
opIF = 0x58 // IF test
|
||||
opEIF = 0x59 // End IF
|
||||
opAND = 0x5a // logical AND
|
||||
opOR = 0x5b // logical OR
|
||||
opNOT = 0x5c // logical NOT
|
||||
opDELTAP1 = 0x5d // DELTA exception P1
|
||||
opSDB = 0x5e // Set Delta Base in the graphics state
|
||||
opSDS = 0x5f // Set Delta Shift in the graphics state
|
||||
opADD = 0x60 // ADD
|
||||
opSUB = 0x61 // SUBtract
|
||||
opDIV = 0x62 // DIVide
|
||||
opMUL = 0x63 // MULtiply
|
||||
opABS = 0x64 // ABSolute value
|
||||
opNEG = 0x65 // NEGate
|
||||
opFLOOR = 0x66 // FLOOR
|
||||
opCEILING = 0x67 // CEILING
|
||||
opROUND00 = 0x68 // ROUND value
|
||||
opROUND01 = 0x69 // .
|
||||
opROUND10 = 0x6a // .
|
||||
opROUND11 = 0x6b // .
|
||||
opNROUND00 = 0x6c // No ROUNDing of value
|
||||
opNROUND01 = 0x6d // .
|
||||
opNROUND10 = 0x6e // .
|
||||
opNROUND11 = 0x6f // .
|
||||
opWCVTF = 0x70 // Write Control Value Table in Funits
|
||||
opDELTAP2 = 0x71 // DELTA exception P2
|
||||
opDELTAP3 = 0x72 // DELTA exception P3
|
||||
opDELTAC1 = 0x73 // DELTA exception C1
|
||||
opDELTAC2 = 0x74 // DELTA exception C2
|
||||
opDELTAC3 = 0x75 // DELTA exception C3
|
||||
opSROUND = 0x76 // Super ROUND
|
||||
opS45ROUND = 0x77 // Super ROUND 45 degrees
|
||||
opJROT = 0x78 // Jump Relative On True
|
||||
opJROF = 0x79 // Jump Relative On False
|
||||
opROFF = 0x7a // Round OFF
|
||||
op_0x7b = 0x7b // deprecated
|
||||
opRUTG = 0x7c // Round Up To Grid
|
||||
opRDTG = 0x7d // Round Down To Grid
|
||||
opSANGW = 0x7e // Set ANGle Weight
|
||||
opAA = 0x7f // Adjust Angle
|
||||
opFLIPPT = 0x80 // FLIP PoinT
|
||||
opFLIPRGON = 0x81 // FLIP RanGe ON
|
||||
opFLIPRGOFF = 0x82 // FLIP RanGe OFF
|
||||
op_0x83 = 0x83 // deprecated
|
||||
op_0x84 = 0x84 // deprecated
|
||||
opSCANCTRL = 0x85 // SCAN conversion ConTRoL
|
||||
opSDPVTL0 = 0x86 // Set Dual Projection Vector To Line
|
||||
opSDPVTL1 = 0x87 // .
|
||||
opGETINFO = 0x88 // GET INFOrmation
|
||||
opIDEF = 0x89 // Instruction DEFinition
|
||||
opROLL = 0x8a // ROLL the top three stack elements
|
||||
opMAX = 0x8b // MAXimum of top two stack elements
|
||||
opMIN = 0x8c // MINimum of top two stack elements
|
||||
opSCANTYPE = 0x8d // SCANTYPE
|
||||
opINSTCTRL = 0x8e // INSTRuction execution ConTRoL
|
||||
op_0x8f = 0x8f
|
||||
op_0x90 = 0x90
|
||||
op_0x91 = 0x91
|
||||
op_0x92 = 0x92
|
||||
op_0x93 = 0x93
|
||||
op_0x94 = 0x94
|
||||
op_0x95 = 0x95
|
||||
op_0x96 = 0x96
|
||||
op_0x97 = 0x97
|
||||
op_0x98 = 0x98
|
||||
op_0x99 = 0x99
|
||||
op_0x9a = 0x9a
|
||||
op_0x9b = 0x9b
|
||||
op_0x9c = 0x9c
|
||||
op_0x9d = 0x9d
|
||||
op_0x9e = 0x9e
|
||||
op_0x9f = 0x9f
|
||||
op_0xa0 = 0xa0
|
||||
op_0xa1 = 0xa1
|
||||
op_0xa2 = 0xa2
|
||||
op_0xa3 = 0xa3
|
||||
op_0xa4 = 0xa4
|
||||
op_0xa5 = 0xa5
|
||||
op_0xa6 = 0xa6
|
||||
op_0xa7 = 0xa7
|
||||
op_0xa8 = 0xa8
|
||||
op_0xa9 = 0xa9
|
||||
op_0xaa = 0xaa
|
||||
op_0xab = 0xab
|
||||
op_0xac = 0xac
|
||||
op_0xad = 0xad
|
||||
op_0xae = 0xae
|
||||
op_0xaf = 0xaf
|
||||
opPUSHB000 = 0xb0 // PUSH Bytes
|
||||
opPUSHB001 = 0xb1 // .
|
||||
opPUSHB010 = 0xb2 // .
|
||||
opPUSHB011 = 0xb3 // .
|
||||
opPUSHB100 = 0xb4 // .
|
||||
opPUSHB101 = 0xb5 // .
|
||||
opPUSHB110 = 0xb6 // .
|
||||
opPUSHB111 = 0xb7 // .
|
||||
opPUSHW000 = 0xb8 // PUSH Words
|
||||
opPUSHW001 = 0xb9 // .
|
||||
opPUSHW010 = 0xba // .
|
||||
opPUSHW011 = 0xbb // .
|
||||
opPUSHW100 = 0xbc // .
|
||||
opPUSHW101 = 0xbd // .
|
||||
opPUSHW110 = 0xbe // .
|
||||
opPUSHW111 = 0xbf // .
|
||||
opMDRP00000 = 0xc0 // Move Direct Relative Point
|
||||
opMDRP00001 = 0xc1 // .
|
||||
opMDRP00010 = 0xc2 // .
|
||||
opMDRP00011 = 0xc3 // .
|
||||
opMDRP00100 = 0xc4 // .
|
||||
opMDRP00101 = 0xc5 // .
|
||||
opMDRP00110 = 0xc6 // .
|
||||
opMDRP00111 = 0xc7 // .
|
||||
opMDRP01000 = 0xc8 // .
|
||||
opMDRP01001 = 0xc9 // .
|
||||
opMDRP01010 = 0xca // .
|
||||
opMDRP01011 = 0xcb // .
|
||||
opMDRP01100 = 0xcc // .
|
||||
opMDRP01101 = 0xcd // .
|
||||
opMDRP01110 = 0xce // .
|
||||
opMDRP01111 = 0xcf // .
|
||||
opMDRP10000 = 0xd0 // .
|
||||
opMDRP10001 = 0xd1 // .
|
||||
opMDRP10010 = 0xd2 // .
|
||||
opMDRP10011 = 0xd3 // .
|
||||
opMDRP10100 = 0xd4 // .
|
||||
opMDRP10101 = 0xd5 // .
|
||||
opMDRP10110 = 0xd6 // .
|
||||
opMDRP10111 = 0xd7 // .
|
||||
opMDRP11000 = 0xd8 // .
|
||||
opMDRP11001 = 0xd9 // .
|
||||
opMDRP11010 = 0xda // .
|
||||
opMDRP11011 = 0xdb // .
|
||||
opMDRP11100 = 0xdc // .
|
||||
opMDRP11101 = 0xdd // .
|
||||
opMDRP11110 = 0xde // .
|
||||
opMDRP11111 = 0xdf // .
|
||||
opMIRP00000 = 0xe0 // Move Indirect Relative Point
|
||||
opMIRP00001 = 0xe1 // .
|
||||
opMIRP00010 = 0xe2 // .
|
||||
opMIRP00011 = 0xe3 // .
|
||||
opMIRP00100 = 0xe4 // .
|
||||
opMIRP00101 = 0xe5 // .
|
||||
opMIRP00110 = 0xe6 // .
|
||||
opMIRP00111 = 0xe7 // .
|
||||
opMIRP01000 = 0xe8 // .
|
||||
opMIRP01001 = 0xe9 // .
|
||||
opMIRP01010 = 0xea // .
|
||||
opMIRP01011 = 0xeb // .
|
||||
opMIRP01100 = 0xec // .
|
||||
opMIRP01101 = 0xed // .
|
||||
opMIRP01110 = 0xee // .
|
||||
opMIRP01111 = 0xef // .
|
||||
opMIRP10000 = 0xf0 // .
|
||||
opMIRP10001 = 0xf1 // .
|
||||
opMIRP10010 = 0xf2 // .
|
||||
opMIRP10011 = 0xf3 // .
|
||||
opMIRP10100 = 0xf4 // .
|
||||
opMIRP10101 = 0xf5 // .
|
||||
opMIRP10110 = 0xf6 // .
|
||||
opMIRP10111 = 0xf7 // .
|
||||
opMIRP11000 = 0xf8 // .
|
||||
opMIRP11001 = 0xf9 // .
|
||||
opMIRP11010 = 0xfa // .
|
||||
opMIRP11011 = 0xfb // .
|
||||
opMIRP11100 = 0xfc // .
|
||||
opMIRP11101 = 0xfd // .
|
||||
opMIRP11110 = 0xfe // .
|
||||
opMIRP11111 = 0xff // .
|
||||
)
|
||||
|
||||
// popCount is the number of stack elements that each opcode pops.
|
||||
var popCount = [256]uint8{
|
||||
// 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
|
||||
0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 5, // 0x00 - 0x0f
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, // 0x10 - 0x1f
|
||||
1, 1, 0, 2, 0, 1, 1, 2, 0, 1, 2, 1, 1, 0, 1, 1, // 0x20 - 0x2f
|
||||
0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 2, 2, 0, 0, 2, 2, // 0x30 - 0x3f
|
||||
0, 0, 2, 1, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, // 0x40 - 0x4f
|
||||
2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 2, 2, 1, 1, 1, 1, // 0x50 - 0x5f
|
||||
2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6f
|
||||
2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0, 1, 1, // 0x70 - 0x7f
|
||||
0, 2, 2, 0, 0, 1, 2, 2, 1, 1, 3, 2, 2, 1, 2, 0, // 0x80 - 0x8f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x90 - 0x9f
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xa0 - 0xaf
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0 - 0xbf
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xc0 - 0xcf
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xd0 - 0xdf
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0 - 0xef
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0 - 0xff
|
||||
}
|
||||
554
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/truetype.go
сгенерированный
поставляемый
554
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/truetype.go
сгенерированный
поставляемый
@@ -1,554 +0,0 @@
|
||||
// Copyright 2010 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
// Package truetype provides a parser for the TTF and TTC file formats.
|
||||
// Those formats are documented at http://developer.apple.com/fonts/TTRefMan/
|
||||
// and http://www.microsoft.com/typography/otspec/
|
||||
//
|
||||
// Some of a font's methods provide lengths or co-ordinates, e.g. bounds, font
|
||||
// metrics and control points. All these methods take a scale parameter, which
|
||||
// is the number of device units in 1 em. For example, if 1 em is 10 pixels and
|
||||
// 1 pixel is 64 units, then scale is 640. If the device space involves pixels,
|
||||
// 64 units per pixel is recommended, since that is what the bytecode hinter
|
||||
// uses when snapping point co-ordinates to the pixel grid.
|
||||
//
|
||||
// To measure a TrueType font in ideal FUnit space, use scale equal to
|
||||
// font.FUnitsPerEm().
|
||||
package truetype
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// An Index is a Font's index of a rune.
|
||||
type Index uint16
|
||||
|
||||
// A Bounds holds the co-ordinate range of one or more glyphs.
|
||||
// The endpoints are inclusive.
|
||||
type Bounds struct {
|
||||
XMin, YMin, XMax, YMax int32
|
||||
}
|
||||
|
||||
// An HMetric holds the horizontal metrics of a single glyph.
|
||||
type HMetric struct {
|
||||
AdvanceWidth, LeftSideBearing int32
|
||||
}
|
||||
|
||||
// A VMetric holds the vertical metrics of a single glyph.
|
||||
type VMetric struct {
|
||||
AdvanceHeight, TopSideBearing int32
|
||||
}
|
||||
|
||||
// A FormatError reports that the input is not a valid TrueType font.
|
||||
type FormatError string
|
||||
|
||||
func (e FormatError) Error() string {
|
||||
return "freetype: invalid TrueType format: " + string(e)
|
||||
}
|
||||
|
||||
// An UnsupportedError reports that the input uses a valid but unimplemented
|
||||
// TrueType feature.
|
||||
type UnsupportedError string
|
||||
|
||||
func (e UnsupportedError) Error() string {
|
||||
return "freetype: unsupported TrueType feature: " + string(e)
|
||||
}
|
||||
|
||||
// u32 returns the big-endian uint32 at b[i:].
|
||||
func u32(b []byte, i int) uint32 {
|
||||
return uint32(b[i])<<24 | uint32(b[i+1])<<16 | uint32(b[i+2])<<8 | uint32(b[i+3])
|
||||
}
|
||||
|
||||
// u16 returns the big-endian uint16 at b[i:].
|
||||
func u16(b []byte, i int) uint16 {
|
||||
return uint16(b[i])<<8 | uint16(b[i+1])
|
||||
}
|
||||
|
||||
// readTable returns a slice of the TTF data given by a table's directory entry.
|
||||
func readTable(ttf []byte, offsetLength []byte) ([]byte, error) {
|
||||
offset := int(u32(offsetLength, 0))
|
||||
if offset < 0 {
|
||||
return nil, FormatError(fmt.Sprintf("offset too large: %d", uint32(offset)))
|
||||
}
|
||||
length := int(u32(offsetLength, 4))
|
||||
if length < 0 {
|
||||
return nil, FormatError(fmt.Sprintf("length too large: %d", uint32(length)))
|
||||
}
|
||||
end := offset + length
|
||||
if end < 0 || end > len(ttf) {
|
||||
return nil, FormatError(fmt.Sprintf("offset + length too large: %d", uint32(offset)+uint32(length)))
|
||||
}
|
||||
return ttf[offset:end], nil
|
||||
}
|
||||
|
||||
const (
|
||||
locaOffsetFormatUnknown int = iota
|
||||
locaOffsetFormatShort
|
||||
locaOffsetFormatLong
|
||||
)
|
||||
|
||||
// A cm holds a parsed cmap entry.
|
||||
type cm struct {
|
||||
start, end, delta, offset uint32
|
||||
}
|
||||
|
||||
// A Font represents a Truetype font.
|
||||
type Font struct {
|
||||
// Tables sliced from the TTF data. The different tables are documented
|
||||
// at http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html
|
||||
cmap, cvt, fpgm, glyf, hdmx, head, hhea, hmtx, kern, loca, maxp, os2, prep, vmtx []byte
|
||||
|
||||
cmapIndexes []byte
|
||||
|
||||
// Cached values derived from the raw ttf data.
|
||||
cm []cm
|
||||
locaOffsetFormat int
|
||||
nGlyph, nHMetric, nKern int
|
||||
fUnitsPerEm int32
|
||||
bounds Bounds
|
||||
// Values from the maxp section.
|
||||
maxTwilightPoints, maxStorage, maxFunctionDefs, maxStackElements uint16
|
||||
}
|
||||
|
||||
func (f *Font) parseCmap() error {
|
||||
const (
|
||||
cmapFormat4 = 4
|
||||
cmapFormat12 = 12
|
||||
languageIndependent = 0
|
||||
|
||||
// A 32-bit encoding consists of a most-significant 16-bit Platform ID and a
|
||||
// least-significant 16-bit Platform Specific ID. The magic numbers are
|
||||
// specified at https://www.microsoft.com/typography/otspec/name.htm
|
||||
unicodeEncoding = 0x00000003 // PID = 0 (Unicode), PSID = 3 (Unicode 2.0)
|
||||
microsoftSymbolEncoding = 0x00030000 // PID = 3 (Microsoft), PSID = 0 (Symbol)
|
||||
microsoftUCS2Encoding = 0x00030001 // PID = 3 (Microsoft), PSID = 1 (UCS-2)
|
||||
microsoftUCS4Encoding = 0x0003000a // PID = 3 (Microsoft), PSID = 10 (UCS-4)
|
||||
)
|
||||
|
||||
if len(f.cmap) < 4 {
|
||||
return FormatError("cmap too short")
|
||||
}
|
||||
nsubtab := int(u16(f.cmap, 2))
|
||||
if len(f.cmap) < 8*nsubtab+4 {
|
||||
return FormatError("cmap too short")
|
||||
}
|
||||
offset, found, x := 0, false, 4
|
||||
for i := 0; i < nsubtab; i++ {
|
||||
// We read the 16-bit Platform ID and 16-bit Platform Specific ID as a single uint32.
|
||||
// All values are big-endian.
|
||||
pidPsid, o := u32(f.cmap, x), u32(f.cmap, x+4)
|
||||
x += 8
|
||||
// We prefer the Unicode cmap encoding. Failing to find that, we fall
|
||||
// back onto the Microsoft cmap encoding.
|
||||
if pidPsid == unicodeEncoding {
|
||||
offset, found = int(o), true
|
||||
break
|
||||
|
||||
} else if pidPsid == microsoftSymbolEncoding ||
|
||||
pidPsid == microsoftUCS2Encoding ||
|
||||
pidPsid == microsoftUCS4Encoding {
|
||||
|
||||
offset, found = int(o), true
|
||||
// We don't break out of the for loop, so that Unicode can override Microsoft.
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return UnsupportedError("cmap encoding")
|
||||
}
|
||||
if offset <= 0 || offset > len(f.cmap) {
|
||||
return FormatError("bad cmap offset")
|
||||
}
|
||||
|
||||
cmapFormat := u16(f.cmap, offset)
|
||||
switch cmapFormat {
|
||||
case cmapFormat4:
|
||||
language := u16(f.cmap, offset+4)
|
||||
if language != languageIndependent {
|
||||
return UnsupportedError(fmt.Sprintf("language: %d", language))
|
||||
}
|
||||
segCountX2 := int(u16(f.cmap, offset+6))
|
||||
if segCountX2%2 == 1 {
|
||||
return FormatError(fmt.Sprintf("bad segCountX2: %d", segCountX2))
|
||||
}
|
||||
segCount := segCountX2 / 2
|
||||
offset += 14
|
||||
f.cm = make([]cm, segCount)
|
||||
for i := 0; i < segCount; i++ {
|
||||
f.cm[i].end = uint32(u16(f.cmap, offset))
|
||||
offset += 2
|
||||
}
|
||||
offset += 2
|
||||
for i := 0; i < segCount; i++ {
|
||||
f.cm[i].start = uint32(u16(f.cmap, offset))
|
||||
offset += 2
|
||||
}
|
||||
for i := 0; i < segCount; i++ {
|
||||
f.cm[i].delta = uint32(u16(f.cmap, offset))
|
||||
offset += 2
|
||||
}
|
||||
for i := 0; i < segCount; i++ {
|
||||
f.cm[i].offset = uint32(u16(f.cmap, offset))
|
||||
offset += 2
|
||||
}
|
||||
f.cmapIndexes = f.cmap[offset:]
|
||||
return nil
|
||||
|
||||
case cmapFormat12:
|
||||
if u16(f.cmap, offset+2) != 0 {
|
||||
return FormatError(fmt.Sprintf("cmap format: % x", f.cmap[offset:offset+4]))
|
||||
}
|
||||
length := u32(f.cmap, offset+4)
|
||||
language := u32(f.cmap, offset+8)
|
||||
if language != languageIndependent {
|
||||
return UnsupportedError(fmt.Sprintf("language: %d", language))
|
||||
}
|
||||
nGroups := u32(f.cmap, offset+12)
|
||||
if length != 12*nGroups+16 {
|
||||
return FormatError("inconsistent cmap length")
|
||||
}
|
||||
offset += 16
|
||||
f.cm = make([]cm, nGroups)
|
||||
for i := uint32(0); i < nGroups; i++ {
|
||||
f.cm[i].start = u32(f.cmap, offset+0)
|
||||
f.cm[i].end = u32(f.cmap, offset+4)
|
||||
f.cm[i].delta = u32(f.cmap, offset+8) - f.cm[i].start
|
||||
offset += 12
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return UnsupportedError(fmt.Sprintf("cmap format: %d", cmapFormat))
|
||||
}
|
||||
|
||||
func (f *Font) parseHead() error {
|
||||
if len(f.head) != 54 {
|
||||
return FormatError(fmt.Sprintf("bad head length: %d", len(f.head)))
|
||||
}
|
||||
f.fUnitsPerEm = int32(u16(f.head, 18))
|
||||
f.bounds.XMin = int32(int16(u16(f.head, 36)))
|
||||
f.bounds.YMin = int32(int16(u16(f.head, 38)))
|
||||
f.bounds.XMax = int32(int16(u16(f.head, 40)))
|
||||
f.bounds.YMax = int32(int16(u16(f.head, 42)))
|
||||
switch i := u16(f.head, 50); i {
|
||||
case 0:
|
||||
f.locaOffsetFormat = locaOffsetFormatShort
|
||||
case 1:
|
||||
f.locaOffsetFormat = locaOffsetFormatLong
|
||||
default:
|
||||
return FormatError(fmt.Sprintf("bad indexToLocFormat: %d", i))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Font) parseHhea() error {
|
||||
if len(f.hhea) != 36 {
|
||||
return FormatError(fmt.Sprintf("bad hhea length: %d", len(f.hhea)))
|
||||
}
|
||||
f.nHMetric = int(u16(f.hhea, 34))
|
||||
if 4*f.nHMetric+2*(f.nGlyph-f.nHMetric) != len(f.hmtx) {
|
||||
return FormatError(fmt.Sprintf("bad hmtx length: %d", len(f.hmtx)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Font) parseKern() error {
|
||||
// Apple's TrueType documentation (http://developer.apple.com/fonts/TTRefMan/RM06/Chap6kern.html) says:
|
||||
// "Previous versions of the 'kern' table defined both the version and nTables fields in the header
|
||||
// as UInt16 values and not UInt32 values. Use of the older format on the Mac OS is discouraged
|
||||
// (although AAT can sense an old kerning table and still make correct use of it). Microsoft
|
||||
// Windows still uses the older format for the 'kern' table and will not recognize the newer one.
|
||||
// Fonts targeted for the Mac OS only should use the new format; fonts targeted for both the Mac OS
|
||||
// and Windows should use the old format."
|
||||
// Since we expect that almost all fonts aim to be Windows-compatible, we only parse the "older" format,
|
||||
// just like the C Freetype implementation.
|
||||
if len(f.kern) == 0 {
|
||||
if f.nKern != 0 {
|
||||
return FormatError("bad kern table length")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if len(f.kern) < 18 {
|
||||
return FormatError("kern data too short")
|
||||
}
|
||||
version, offset := u16(f.kern, 0), 2
|
||||
if version != 0 {
|
||||
return UnsupportedError(fmt.Sprintf("kern version: %d", version))
|
||||
}
|
||||
n, offset := u16(f.kern, offset), offset+2
|
||||
if n != 1 {
|
||||
return UnsupportedError(fmt.Sprintf("kern nTables: %d", n))
|
||||
}
|
||||
offset += 2
|
||||
length, offset := int(u16(f.kern, offset)), offset+2
|
||||
coverage, offset := u16(f.kern, offset), offset+2
|
||||
if coverage != 0x0001 {
|
||||
// We only support horizontal kerning.
|
||||
return UnsupportedError(fmt.Sprintf("kern coverage: 0x%04x", coverage))
|
||||
}
|
||||
f.nKern, offset = int(u16(f.kern, offset)), offset+2
|
||||
if 6*f.nKern != length-14 {
|
||||
return FormatError("bad kern table length")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Font) parseMaxp() error {
|
||||
if len(f.maxp) != 32 {
|
||||
return FormatError(fmt.Sprintf("bad maxp length: %d", len(f.maxp)))
|
||||
}
|
||||
f.nGlyph = int(u16(f.maxp, 4))
|
||||
f.maxTwilightPoints = u16(f.maxp, 16)
|
||||
f.maxStorage = u16(f.maxp, 18)
|
||||
f.maxFunctionDefs = u16(f.maxp, 20)
|
||||
f.maxStackElements = u16(f.maxp, 24)
|
||||
return nil
|
||||
}
|
||||
|
||||
// scale returns x divided by f.fUnitsPerEm, rounded to the nearest integer.
|
||||
func (f *Font) scale(x int32) int32 {
|
||||
if x >= 0 {
|
||||
x += f.fUnitsPerEm / 2
|
||||
} else {
|
||||
x -= f.fUnitsPerEm / 2
|
||||
}
|
||||
return x / f.fUnitsPerEm
|
||||
}
|
||||
|
||||
// Bounds returns the union of a Font's glyphs' bounds.
|
||||
func (f *Font) Bounds(scale int32) Bounds {
|
||||
b := f.bounds
|
||||
b.XMin = f.scale(scale * b.XMin)
|
||||
b.YMin = f.scale(scale * b.YMin)
|
||||
b.XMax = f.scale(scale * b.XMax)
|
||||
b.YMax = f.scale(scale * b.YMax)
|
||||
return b
|
||||
}
|
||||
|
||||
// FUnitsPerEm returns the number of FUnits in a Font's em-square's side.
|
||||
func (f *Font) FUnitsPerEm() int32 {
|
||||
return f.fUnitsPerEm
|
||||
}
|
||||
|
||||
// Index returns a Font's index for the given rune.
|
||||
func (f *Font) Index(x rune) Index {
|
||||
c := uint32(x)
|
||||
for i, j := 0, len(f.cm); i < j; {
|
||||
h := i + (j-i)/2
|
||||
cm := &f.cm[h]
|
||||
if c < cm.start {
|
||||
j = h
|
||||
} else if cm.end < c {
|
||||
i = h + 1
|
||||
} else if cm.offset == 0 {
|
||||
return Index(c + cm.delta)
|
||||
} else {
|
||||
offset := int(cm.offset) + 2*(h-len(f.cm)+int(c-cm.start))
|
||||
return Index(u16(f.cmapIndexes, offset))
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// unscaledHMetric returns the unscaled horizontal metrics for the glyph with
|
||||
// the given index.
|
||||
func (f *Font) unscaledHMetric(i Index) (h HMetric) {
|
||||
j := int(i)
|
||||
if j < 0 || f.nGlyph <= j {
|
||||
return HMetric{}
|
||||
}
|
||||
if j >= f.nHMetric {
|
||||
p := 4 * (f.nHMetric - 1)
|
||||
return HMetric{
|
||||
AdvanceWidth: int32(u16(f.hmtx, p)),
|
||||
LeftSideBearing: int32(int16(u16(f.hmtx, p+2*(j-f.nHMetric)+4))),
|
||||
}
|
||||
}
|
||||
return HMetric{
|
||||
AdvanceWidth: int32(u16(f.hmtx, 4*j)),
|
||||
LeftSideBearing: int32(int16(u16(f.hmtx, 4*j+2))),
|
||||
}
|
||||
}
|
||||
|
||||
// HMetric returns the horizontal metrics for the glyph with the given index.
|
||||
func (f *Font) HMetric(scale int32, i Index) HMetric {
|
||||
h := f.unscaledHMetric(i)
|
||||
h.AdvanceWidth = f.scale(scale * h.AdvanceWidth)
|
||||
h.LeftSideBearing = f.scale(scale * h.LeftSideBearing)
|
||||
return h
|
||||
}
|
||||
|
||||
// unscaledVMetric returns the unscaled vertical metrics for the glyph with
|
||||
// the given index. yMax is the top of the glyph's bounding box.
|
||||
func (f *Font) unscaledVMetric(i Index, yMax int32) (v VMetric) {
|
||||
j := int(i)
|
||||
if j < 0 || f.nGlyph <= j {
|
||||
return VMetric{}
|
||||
}
|
||||
if 4*j+4 <= len(f.vmtx) {
|
||||
return VMetric{
|
||||
AdvanceHeight: int32(u16(f.vmtx, 4*j)),
|
||||
TopSideBearing: int32(int16(u16(f.vmtx, 4*j+2))),
|
||||
}
|
||||
}
|
||||
// The OS/2 table has grown over time.
|
||||
// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6OS2.html
|
||||
// says that it was originally 68 bytes. Optional fields, including
|
||||
// the ascender and descender, are described at
|
||||
// http://www.microsoft.com/typography/otspec/os2.htm
|
||||
if len(f.os2) >= 72 {
|
||||
sTypoAscender := int32(int16(u16(f.os2, 68)))
|
||||
sTypoDescender := int32(int16(u16(f.os2, 70)))
|
||||
return VMetric{
|
||||
AdvanceHeight: sTypoAscender - sTypoDescender,
|
||||
TopSideBearing: sTypoAscender - yMax,
|
||||
}
|
||||
}
|
||||
return VMetric{
|
||||
AdvanceHeight: f.fUnitsPerEm,
|
||||
TopSideBearing: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// VMetric returns the vertical metrics for the glyph with the given index.
|
||||
func (f *Font) VMetric(scale int32, i Index) VMetric {
|
||||
// TODO: should 0 be bounds.YMax?
|
||||
v := f.unscaledVMetric(i, 0)
|
||||
v.AdvanceHeight = f.scale(scale * v.AdvanceHeight)
|
||||
v.TopSideBearing = f.scale(scale * v.TopSideBearing)
|
||||
return v
|
||||
}
|
||||
|
||||
// Kerning returns the kerning for the given glyph pair.
|
||||
func (f *Font) Kerning(scale int32, i0, i1 Index) int32 {
|
||||
if f.nKern == 0 {
|
||||
return 0
|
||||
}
|
||||
g := uint32(i0)<<16 | uint32(i1)
|
||||
lo, hi := 0, f.nKern
|
||||
for lo < hi {
|
||||
i := (lo + hi) / 2
|
||||
ig := u32(f.kern, 18+6*i)
|
||||
if ig < g {
|
||||
lo = i + 1
|
||||
} else if ig > g {
|
||||
hi = i
|
||||
} else {
|
||||
return f.scale(scale * int32(int16(u16(f.kern, 22+6*i))))
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Parse returns a new Font for the given TTF or TTC data.
|
||||
//
|
||||
// For TrueType Collections, the first font in the collection is parsed.
|
||||
func Parse(ttf []byte) (font *Font, err error) {
|
||||
return parse(ttf, 0)
|
||||
}
|
||||
|
||||
func parse(ttf []byte, offset int) (font *Font, err error) {
|
||||
if len(ttf)-offset < 12 {
|
||||
err = FormatError("TTF data is too short")
|
||||
return
|
||||
}
|
||||
originalOffset := offset
|
||||
magic, offset := u32(ttf, offset), offset+4
|
||||
switch magic {
|
||||
case 0x00010000:
|
||||
// No-op.
|
||||
case 0x74746366: // "ttcf" as a big-endian uint32.
|
||||
if originalOffset != 0 {
|
||||
err = FormatError("recursive TTC")
|
||||
return
|
||||
}
|
||||
ttcVersion, offset := u32(ttf, offset), offset+4
|
||||
if ttcVersion != 0x00010000 {
|
||||
// TODO: support TTC version 2.0, once I have such a .ttc file to test with.
|
||||
err = FormatError("bad TTC version")
|
||||
return
|
||||
}
|
||||
numFonts, offset := int(u32(ttf, offset)), offset+4
|
||||
if numFonts <= 0 {
|
||||
err = FormatError("bad number of TTC fonts")
|
||||
return
|
||||
}
|
||||
if len(ttf[offset:])/4 < numFonts {
|
||||
err = FormatError("TTC offset table is too short")
|
||||
return
|
||||
}
|
||||
// TODO: provide an API to select which font in a TrueType collection to return,
|
||||
// not just the first one. This may require an API to parse a TTC's name tables,
|
||||
// so users of this package can select the font in a TTC by name.
|
||||
offset = int(u32(ttf, offset))
|
||||
if offset <= 0 || offset > len(ttf) {
|
||||
err = FormatError("bad TTC offset")
|
||||
return
|
||||
}
|
||||
return parse(ttf, offset)
|
||||
default:
|
||||
err = FormatError("bad TTF version")
|
||||
return
|
||||
}
|
||||
n, offset := int(u16(ttf, offset)), offset+2
|
||||
if len(ttf) < 16*n+12 {
|
||||
err = FormatError("TTF data is too short")
|
||||
return
|
||||
}
|
||||
f := new(Font)
|
||||
// Assign the table slices.
|
||||
for i := 0; i < n; i++ {
|
||||
x := 16*i + 12
|
||||
switch string(ttf[x : x+4]) {
|
||||
case "cmap":
|
||||
f.cmap, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "cvt ":
|
||||
f.cvt, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "fpgm":
|
||||
f.fpgm, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "glyf":
|
||||
f.glyf, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "hdmx":
|
||||
f.hdmx, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "head":
|
||||
f.head, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "hhea":
|
||||
f.hhea, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "hmtx":
|
||||
f.hmtx, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "kern":
|
||||
f.kern, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "loca":
|
||||
f.loca, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "maxp":
|
||||
f.maxp, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "OS/2":
|
||||
f.os2, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "prep":
|
||||
f.prep, err = readTable(ttf, ttf[x+8:x+16])
|
||||
case "vmtx":
|
||||
f.vmtx, err = readTable(ttf, ttf[x+8:x+16])
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// Parse and sanity-check the TTF data.
|
||||
if err = f.parseHead(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = f.parseMaxp(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = f.parseCmap(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = f.parseKern(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = f.parseHhea(); err != nil {
|
||||
return
|
||||
}
|
||||
font = f
|
||||
return
|
||||
}
|
||||
366
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/truetype_test.go
сгенерированный
поставляемый
366
Godeps/_workspace/src/code.google.com/p/freetype-go/freetype/truetype/truetype_test.go
сгенерированный
поставляемый
@@ -1,366 +0,0 @@
|
||||
// Copyright 2012 The Freetype-Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by your choice of either the
|
||||
// FreeType License or the GNU General Public License version 2 (or
|
||||
// any later version), both of which can be found in the LICENSE file.
|
||||
|
||||
package truetype
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func parseTestdataFont(name string) (font *Font, testdataIsOptional bool, err error) {
|
||||
b, err := ioutil.ReadFile(fmt.Sprintf("../../testdata/%s.ttf", name))
|
||||
if err != nil {
|
||||
// The "x-foo" fonts are optional tests, as they are not checked
|
||||
// in for copyright or file size reasons.
|
||||
return nil, strings.HasPrefix(name, "x-"), fmt.Errorf("%s: ReadFile: %v", name, err)
|
||||
}
|
||||
font, err = Parse(b)
|
||||
if err != nil {
|
||||
return nil, true, fmt.Errorf("%s: Parse: %v", name, err)
|
||||
}
|
||||
return font, false, nil
|
||||
}
|
||||
|
||||
// TestParse tests that the luxisr.ttf metrics and glyphs are parsed correctly.
|
||||
// The numerical values can be manually verified by examining luxisr.ttx.
|
||||
func TestParse(t *testing.T) {
|
||||
font, _, err := parseTestdataFont("luxisr")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := font.FUnitsPerEm(), int32(2048); got != want {
|
||||
t.Errorf("FUnitsPerEm: got %v, want %v", got, want)
|
||||
}
|
||||
fupe := font.FUnitsPerEm()
|
||||
if got, want := font.Bounds(fupe), (Bounds{-441, -432, 2024, 2033}); got != want {
|
||||
t.Errorf("Bounds: got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
i0 := font.Index('A')
|
||||
i1 := font.Index('V')
|
||||
if i0 != 36 || i1 != 57 {
|
||||
t.Fatalf("Index: i0, i1 = %d, %d, want 36, 57", i0, i1)
|
||||
}
|
||||
if got, want := font.HMetric(fupe, i0), (HMetric{1366, 19}); got != want {
|
||||
t.Errorf("HMetric: got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := font.VMetric(fupe, i0), (VMetric{2465, 553}); got != want {
|
||||
t.Errorf("VMetric: got %v, want %v", got, want)
|
||||
}
|
||||
if got, want := font.Kerning(fupe, i0, i1), int32(-144); got != want {
|
||||
t.Errorf("Kerning: got %v, want %v", got, want)
|
||||
}
|
||||
|
||||
g := NewGlyphBuf()
|
||||
err = g.Load(font, fupe, i0, NoHinting)
|
||||
if err != nil {
|
||||
t.Fatalf("Load: %v", err)
|
||||
}
|
||||
g0 := &GlyphBuf{
|
||||
B: g.B,
|
||||
Point: g.Point,
|
||||
End: g.End,
|
||||
}
|
||||
g1 := &GlyphBuf{
|
||||
B: Bounds{19, 0, 1342, 1480},
|
||||
Point: []Point{
|
||||
{19, 0, 51},
|
||||
{581, 1480, 1},
|
||||
{789, 1480, 51},
|
||||
{1342, 0, 1},
|
||||
{1116, 0, 35},
|
||||
{962, 410, 3},
|
||||
{368, 410, 33},
|
||||
{214, 0, 3},
|
||||
{428, 566, 19},
|
||||
{904, 566, 33},
|
||||
{667, 1200, 3},
|
||||
},
|
||||
End: []int{8, 11},
|
||||
}
|
||||
if got, want := fmt.Sprint(g0), fmt.Sprint(g1); got != want {
|
||||
t.Errorf("GlyphBuf:\ngot %v\nwant %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIndex(t *testing.T) {
|
||||
testCases := map[string]map[rune]Index{
|
||||
"luxisr": {
|
||||
' ': 3,
|
||||
'!': 4,
|
||||
'A': 36,
|
||||
'V': 57,
|
||||
'É': 101,
|
||||
'fl': 193,
|
||||
'\u22c5': 385,
|
||||
'中': 0,
|
||||
},
|
||||
|
||||
// The x-etc test cases use those versions of the .ttf files provided
|
||||
// by Ubuntu 14.04. See testdata/make-other-hinting-txts.sh for details.
|
||||
|
||||
"x-arial-bold": {
|
||||
' ': 3,
|
||||
'+': 14,
|
||||
'0': 19,
|
||||
'_': 66,
|
||||
'w': 90,
|
||||
'~': 97,
|
||||
'Ä': 98,
|
||||
'fl': 192,
|
||||
'½': 242,
|
||||
'σ': 305,
|
||||
'λ': 540,
|
||||
'ỹ': 1275,
|
||||
'\u04e9': 1319,
|
||||
'中': 0,
|
||||
},
|
||||
"x-deja-vu-sans-oblique": {
|
||||
' ': 3,
|
||||
'*': 13,
|
||||
'Œ': 276,
|
||||
'ω': 861,
|
||||
'‡': 2571,
|
||||
'⊕': 3110,
|
||||
'fl': 4728,
|
||||
'\ufb03': 4729,
|
||||
'\ufffd': 4813,
|
||||
// TODO: '\U0001f640': ???,
|
||||
'中': 0,
|
||||
},
|
||||
"x-droid-sans-japanese": {
|
||||
' ': 0,
|
||||
'\u3000': 3,
|
||||
'\u3041': 25,
|
||||
'\u30fe': 201,
|
||||
'\uff61': 202,
|
||||
'\uff67': 208,
|
||||
'\uff9e': 263,
|
||||
'\uff9f': 264,
|
||||
'\u4e00': 265,
|
||||
'\u557e': 1000,
|
||||
'\u61b6': 2024,
|
||||
'\u6ede': 3177,
|
||||
'\u7505': 3555,
|
||||
'\u81e3': 4602,
|
||||
'\u81e5': 4603,
|
||||
'\u81e7': 4604,
|
||||
'\u81e8': 4605,
|
||||
'\u81ea': 4606,
|
||||
'\u81ed': 4607,
|
||||
'\u81f3': 4608,
|
||||
'\u81f4': 4609,
|
||||
'\u91c7': 5796,
|
||||
'\u9fa0': 6620,
|
||||
'\u203e': 12584,
|
||||
},
|
||||
"x-times-new-roman": {
|
||||
' ': 3,
|
||||
':': 29,
|
||||
'fl': 192,
|
||||
'Ŀ': 273,
|
||||
'♠': 388,
|
||||
'Ŗ': 451,
|
||||
'Σ': 520,
|
||||
'\u200D': 745,
|
||||
'Ẽ': 1216,
|
||||
'\u04e9': 1319,
|
||||
'中': 0,
|
||||
},
|
||||
}
|
||||
for name, wants := range testCases {
|
||||
font, testdataIsOptional, err := parseTestdataFont(name)
|
||||
if err != nil {
|
||||
if testdataIsOptional {
|
||||
t.Log(err)
|
||||
} else {
|
||||
t.Fatal(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
for r, want := range wants {
|
||||
if got := font.Index(r); got != want {
|
||||
t.Errorf("%s: Index of %q, aka %U: got %d, want %d", name, r, r, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type scalingTestData struct {
|
||||
advanceWidth int32
|
||||
bounds Bounds
|
||||
points []Point
|
||||
}
|
||||
|
||||
// scalingTestParse parses a line of points like
|
||||
// 213 -22 -111 236 555;-22 -111 1, 178 555 1, 236 555 1, 36 -111 1
|
||||
// The line will not have a trailing "\n".
|
||||
func scalingTestParse(line string) (ret scalingTestData) {
|
||||
next := func(s string) (string, int32) {
|
||||
t, i := "", strings.Index(s, " ")
|
||||
if i != -1 {
|
||||
s, t = s[:i], s[i+1:]
|
||||
}
|
||||
x, _ := strconv.Atoi(s)
|
||||
return t, int32(x)
|
||||
}
|
||||
|
||||
i := strings.Index(line, ";")
|
||||
prefix, line := line[:i], line[i+1:]
|
||||
|
||||
prefix, ret.advanceWidth = next(prefix)
|
||||
prefix, ret.bounds.XMin = next(prefix)
|
||||
prefix, ret.bounds.YMin = next(prefix)
|
||||
prefix, ret.bounds.XMax = next(prefix)
|
||||
prefix, ret.bounds.YMax = next(prefix)
|
||||
|
||||
ret.points = make([]Point, 0, 1+strings.Count(line, ","))
|
||||
for len(line) > 0 {
|
||||
s := line
|
||||
if i := strings.Index(line, ","); i != -1 {
|
||||
s, line = line[:i], line[i+1:]
|
||||
for len(line) > 0 && line[0] == ' ' {
|
||||
line = line[1:]
|
||||
}
|
||||
} else {
|
||||
line = ""
|
||||
}
|
||||
s, x := next(s)
|
||||
s, y := next(s)
|
||||
s, f := next(s)
|
||||
ret.points = append(ret.points, Point{X: x, Y: y, Flags: uint32(f)})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// scalingTestEquals is equivalent to, but faster than, calling
|
||||
// reflect.DeepEquals(a, b), and also returns the index of the first non-equal
|
||||
// element. It also treats a nil []Point and an empty non-nil []Point as equal.
|
||||
// a and b must have equal length.
|
||||
func scalingTestEquals(a, b []Point) (index int, equals bool) {
|
||||
for i, p := range a {
|
||||
if p != b[i] {
|
||||
return i, false
|
||||
}
|
||||
}
|
||||
return 0, true
|
||||
}
|
||||
|
||||
var scalingTestCases = []struct {
|
||||
name string
|
||||
size int32
|
||||
}{
|
||||
{"luxisr", 12},
|
||||
{"x-arial-bold", 11},
|
||||
{"x-deja-vu-sans-oblique", 17},
|
||||
{"x-droid-sans-japanese", 9},
|
||||
{"x-times-new-roman", 13},
|
||||
}
|
||||
|
||||
func testScaling(t *testing.T, h Hinting) {
|
||||
for _, tc := range scalingTestCases {
|
||||
font, testdataIsOptional, err := parseTestdataFont(tc.name)
|
||||
if err != nil {
|
||||
if testdataIsOptional {
|
||||
t.Log(err)
|
||||
} else {
|
||||
t.Error(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
hintingStr := "sans"
|
||||
if h != NoHinting {
|
||||
hintingStr = "with"
|
||||
}
|
||||
f, err := os.Open(fmt.Sprintf(
|
||||
"../../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hintingStr))
|
||||
if err != nil {
|
||||
t.Errorf("%s: Open: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
wants := []scalingTestData{}
|
||||
scanner := bufio.NewScanner(f)
|
||||
if scanner.Scan() {
|
||||
major, minor, patch := 0, 0, 0
|
||||
_, err := fmt.Sscanf(scanner.Text(), "freetype version %d.%d.%d", &major, &minor, &patch)
|
||||
if err != nil {
|
||||
t.Errorf("%s: version information: %v", tc.name, err)
|
||||
}
|
||||
if (major < 2) || (major == 2 && minor < 5) || (major == 2 && minor == 5 && patch < 1) {
|
||||
t.Errorf("%s: need freetype version >= 2.5.1.\n"+
|
||||
"Try setting LD_LIBRARY_PATH=/path/to/freetype_built_from_src/objs/.libs/\n"+
|
||||
"and re-running testdata/make-other-hinting-txts.sh",
|
||||
tc.name)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
t.Errorf("%s: no version information", tc.name)
|
||||
continue
|
||||
}
|
||||
for scanner.Scan() {
|
||||
wants = append(wants, scalingTestParse(scanner.Text()))
|
||||
}
|
||||
if err := scanner.Err(); err != nil && err != io.EOF {
|
||||
t.Errorf("%s: Scanner: %v", tc.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
glyphBuf := NewGlyphBuf()
|
||||
for i, want := range wants {
|
||||
if err = glyphBuf.Load(font, tc.size*64, Index(i), h); err != nil {
|
||||
t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err)
|
||||
continue
|
||||
}
|
||||
got := scalingTestData{
|
||||
advanceWidth: glyphBuf.AdvanceWidth,
|
||||
bounds: glyphBuf.B,
|
||||
points: glyphBuf.Point,
|
||||
}
|
||||
|
||||
if got.advanceWidth != want.advanceWidth {
|
||||
t.Errorf("%s: glyph #%d advance width:\ngot %v\nwant %v",
|
||||
tc.name, i, got.advanceWidth, want.advanceWidth)
|
||||
continue
|
||||
}
|
||||
|
||||
if got.bounds != want.bounds {
|
||||
t.Errorf("%s: glyph #%d bounds:\ngot %v\nwant %v",
|
||||
tc.name, i, got.bounds, want.bounds)
|
||||
continue
|
||||
}
|
||||
|
||||
for i := range got.points {
|
||||
got.points[i].Flags &= 0x01
|
||||
}
|
||||
if len(got.points) != len(want.points) {
|
||||
t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\ndifferent slice lengths: %d versus %d",
|
||||
tc.name, i, got.points, want.points, len(got.points), len(want.points))
|
||||
continue
|
||||
}
|
||||
if j, equals := scalingTestEquals(got.points, want.points); !equals {
|
||||
t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\nat index %d: %v versus %v",
|
||||
tc.name, i, got.points, want.points, j, got.points[j], want.points[j])
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalingSansHinting(t *testing.T) {
|
||||
testScaling(t, NoHinting)
|
||||
}
|
||||
|
||||
func TestScalingWithHinting(t *testing.T) {
|
||||
testScaling(t, FullHinting)
|
||||
}
|
||||
1
Godeps/_workspace/src/code.google.com/p/freetype-go/lib/codereview/codereview.cfg
сгенерированный
поставляемый
1
Godeps/_workspace/src/code.google.com/p/freetype-go/lib/codereview/codereview.cfg
сгенерированный
поставляемый
@@ -1 +0,0 @@
|
||||
defaultcc: golang-codereviews@googlegroups.com
|
||||
169
Godeps/_workspace/src/code.google.com/p/freetype-go/licenses/ftl.txt
сгенерированный
поставляемый
169
Godeps/_workspace/src/code.google.com/p/freetype-go/licenses/ftl.txt
сгенерированный
поставляемый
@@ -1,169 +0,0 @@
|
||||
The FreeType Project LICENSE
|
||||
----------------------------
|
||||
|
||||
2006-Jan-27
|
||||
|
||||
Copyright 1996-2002, 2006 by
|
||||
David Turner, Robert Wilhelm, and Werner Lemberg
|
||||
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The FreeType Project is distributed in several archive packages;
|
||||
some of them may contain, in addition to the FreeType font engine,
|
||||
various tools and contributions which rely on, or relate to, the
|
||||
FreeType Project.
|
||||
|
||||
This license applies to all files found in such packages, and
|
||||
which do not fall under their own explicit license. The license
|
||||
affects thus the FreeType font engine, the test programs,
|
||||
documentation and makefiles, at the very least.
|
||||
|
||||
This license was inspired by the BSD, Artistic, and IJG
|
||||
(Independent JPEG Group) licenses, which all encourage inclusion
|
||||
and use of free software in commercial and freeware products
|
||||
alike. As a consequence, its main points are that:
|
||||
|
||||
o We don't promise that this software works. However, we will be
|
||||
interested in any kind of bug reports. (`as is' distribution)
|
||||
|
||||
o You can use this software for whatever you want, in parts or
|
||||
full form, without having to pay us. (`royalty-free' usage)
|
||||
|
||||
o You may not pretend that you wrote this software. If you use
|
||||
it, or only parts of it, in a program, you must acknowledge
|
||||
somewhere in your documentation that you have used the
|
||||
FreeType code. (`credits')
|
||||
|
||||
We specifically permit and encourage the inclusion of this
|
||||
software, with or without modifications, in commercial products.
|
||||
We disclaim all warranties covering The FreeType Project and
|
||||
assume no liability related to The FreeType Project.
|
||||
|
||||
|
||||
Finally, many people asked us for a preferred form for a
|
||||
credit/disclaimer to use in compliance with this license. We thus
|
||||
encourage you to use the following text:
|
||||
|
||||
"""
|
||||
Portions of this software are copyright © <year> The FreeType
|
||||
Project (www.freetype.org). All rights reserved.
|
||||
"""
|
||||
|
||||
Please replace <year> with the value from the FreeType version you
|
||||
actually use.
|
||||
|
||||
|
||||
Legal Terms
|
||||
===========
|
||||
|
||||
0. Definitions
|
||||
--------------
|
||||
|
||||
Throughout this license, the terms `package', `FreeType Project',
|
||||
and `FreeType archive' refer to the set of files originally
|
||||
distributed by the authors (David Turner, Robert Wilhelm, and
|
||||
Werner Lemberg) as the `FreeType Project', be they named as alpha,
|
||||
beta or final release.
|
||||
|
||||
`You' refers to the licensee, or person using the project, where
|
||||
`using' is a generic term including compiling the project's source
|
||||
code as well as linking it to form a `program' or `executable'.
|
||||
This program is referred to as `a program using the FreeType
|
||||
engine'.
|
||||
|
||||
This license applies to all files distributed in the original
|
||||
FreeType Project, including all source code, binaries and
|
||||
documentation, unless otherwise stated in the file in its
|
||||
original, unmodified form as distributed in the original archive.
|
||||
If you are unsure whether or not a particular file is covered by
|
||||
this license, you must contact us to verify this.
|
||||
|
||||
The FreeType Project is copyright (C) 1996-2000 by David Turner,
|
||||
Robert Wilhelm, and Werner Lemberg. All rights reserved except as
|
||||
specified below.
|
||||
|
||||
1. No Warranty
|
||||
--------------
|
||||
|
||||
THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO
|
||||
USE, OF THE FREETYPE PROJECT.
|
||||
|
||||
2. Redistribution
|
||||
-----------------
|
||||
|
||||
This license grants a worldwide, royalty-free, perpetual and
|
||||
irrevocable right and license to use, execute, perform, compile,
|
||||
display, copy, create derivative works of, distribute and
|
||||
sublicense the FreeType Project (in both source and object code
|
||||
forms) and derivative works thereof for any purpose; and to
|
||||
authorize others to exercise some or all of the rights granted
|
||||
herein, subject to the following conditions:
|
||||
|
||||
o Redistribution of source code must retain this license file
|
||||
(`FTL.TXT') unaltered; any additions, deletions or changes to
|
||||
the original files must be clearly indicated in accompanying
|
||||
documentation. The copyright notices of the unaltered,
|
||||
original files must be preserved in all copies of source
|
||||
files.
|
||||
|
||||
o Redistribution in binary form must provide a disclaimer that
|
||||
states that the software is based in part of the work of the
|
||||
FreeType Team, in the distribution documentation. We also
|
||||
encourage you to put an URL to the FreeType web page in your
|
||||
documentation, though this isn't mandatory.
|
||||
|
||||
These conditions apply to any software derived from or based on
|
||||
the FreeType Project, not just the unmodified files. If you use
|
||||
our work, you must acknowledge us. However, no fee need be paid
|
||||
to us.
|
||||
|
||||
3. Advertising
|
||||
--------------
|
||||
|
||||
Neither the FreeType authors and contributors nor you shall use
|
||||
the name of the other for commercial, advertising, or promotional
|
||||
purposes without specific prior written permission.
|
||||
|
||||
We suggest, but do not require, that you use one or more of the
|
||||
following phrases to refer to this software in your documentation
|
||||
or advertising materials: `FreeType Project', `FreeType Engine',
|
||||
`FreeType library', or `FreeType Distribution'.
|
||||
|
||||
As you have not signed this license, you are not required to
|
||||
accept it. However, as the FreeType Project is copyrighted
|
||||
material, only this license, or another one contracted with the
|
||||
authors, grants you the right to use, distribute, and modify it.
|
||||
Therefore, by using, distributing, or modifying the FreeType
|
||||
Project, you indicate that you understand and accept all the terms
|
||||
of this license.
|
||||
|
||||
4. Contacts
|
||||
-----------
|
||||
|
||||
There are two mailing lists related to FreeType:
|
||||
|
||||
o freetype@nongnu.org
|
||||
|
||||
Discusses general use and applications of FreeType, as well as
|
||||
future and wanted additions to the library and distribution.
|
||||
If you are looking for support, start in this list if you
|
||||
haven't found anything to help you in the documentation.
|
||||
|
||||
o freetype-devel@nongnu.org
|
||||
|
||||
Discusses bugs, as well as engine internals, design issues,
|
||||
specific licenses, porting, etc.
|
||||
|
||||
Our home page can be found at
|
||||
|
||||
http://www.freetype.org
|
||||
|
||||
|
||||
--- end of FTL.TXT ---
|
||||
340
Godeps/_workspace/src/code.google.com/p/freetype-go/licenses/gpl.txt
сгенерированный
поставляемый
340
Godeps/_workspace/src/code.google.com/p/freetype-go/licenses/gpl.txt
сгенерированный
поставляемый
@@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
42
Godeps/_workspace/src/code.google.com/p/freetype-go/testdata/COPYING
сгенерированный
поставляемый
42
Godeps/_workspace/src/code.google.com/p/freetype-go/testdata/COPYING
сгенерированный
поставляемый
@@ -1,42 +0,0 @@
|
||||
Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font
|
||||
instruction code copyright (c) 2001 by URW++ GmbH. All Rights
|
||||
Reserved. Luxi is a registered trademark of Bigelow & Holmes Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of these Fonts and associated documentation files (the "Font
|
||||
Software"), to deal in the Font Software, including without
|
||||
limitation the rights to use, copy, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Font Software, and to permit
|
||||
persons to whom the Font Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright and trademark notices and this permission notice
|
||||
shall be included in all copies of one or more of the Font Software.
|
||||
|
||||
The Font Software may not be modified, altered, or added to, and in
|
||||
particular the designs of glyphs or characters in the Fonts may not
|
||||
be modified nor may additional glyphs or characters be added to the
|
||||
Fonts. This License becomes null and void when the Fonts or Font
|
||||
Software have been modified.
|
||||
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
|
||||
BIGELOW & HOLMES INC. OR URW++ GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF
|
||||
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
|
||||
INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT
|
||||
SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the names of Bigelow & Holmes
|
||||
Inc. and URW++ GmbH. shall not be used in advertising or otherwise to
|
||||
promote the sale, use or other dealings in this Font Software without
|
||||
prior written authorization from Bigelow & Holmes Inc. and URW++ GmbH.
|
||||
|
||||
For further information, contact:
|
||||
|
||||
info@urwpp.de
|
||||
or
|
||||
design@bigelowandholmes.com
|
||||
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Ссылка в новой задаче
Block a user