Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小雨青年
freetype
提交
2a5cbfd4
F
freetype
项目概览
小雨青年
/
freetype
通知
14
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
freetype
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2a5cbfd4
编写于
8月 18, 2015
作者:
N
Nigel Tao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Use the fixed.Int26_6 type in package truetype.
上级
a9554eda
变更
8
显示空白变更内容
内联
并排
Showing
8 changed file
with
117 addition
and
103 deletion
+117
-103
example/freetype/main.go
example/freetype/main.go
+2
-2
example/truetype/main.go
example/truetype/main.go
+2
-1
freetype.go
freetype.go
+5
-5
truetype/glyph.go
truetype/glyph.go
+41
-35
truetype/hint.go
truetype/hint.go
+24
-22
truetype/hint_test.go
truetype/hint_test.go
+3
-1
truetype/truetype.go
truetype/truetype.go
+31
-30
truetype/truetype_test.go
truetype/truetype_test.go
+9
-7
未找到文件。
example/freetype/main.go
浏览文件 @
2a5cbfd4
...
...
@@ -116,14 +116,14 @@ func main() {
}
// Draw the text.
pt
:=
freetype
.
Pt
(
10
,
10
+
int
(
c
.
PointToFix
32
(
*
size
)
>>
6
))
pt
:=
freetype
.
Pt
(
10
,
10
+
int
(
c
.
PointToFix
ed
(
*
size
)
>>
6
))
for
_
,
s
:=
range
text
{
_
,
err
=
c
.
DrawString
(
s
,
pt
)
if
err
!=
nil
{
log
.
Println
(
err
)
return
}
pt
.
Y
+=
c
.
PointToFix
32
(
*
size
*
*
spacing
)
pt
.
Y
+=
c
.
PointToFix
ed
(
*
size
*
*
spacing
)
}
// Save that RGBA image to disk.
...
...
example/truetype/main.go
浏览文件 @
2a5cbfd4
...
...
@@ -17,6 +17,7 @@ import (
"log"
"github.com/golang/freetype/truetype"
"golang.org/x/image/math/fixed"
)
var
fontfile
=
flag
.
String
(
"fontfile"
,
"../../testdata/luxisr.ttf"
,
"filename of the ttf font"
)
...
...
@@ -56,7 +57,7 @@ func main() {
log
.
Println
(
err
)
return
}
fupe
:=
f
ont
.
FUnitsPerEm
(
)
fupe
:=
f
ixed
.
Int26_6
(
font
.
FUnitsPerEm
()
)
printBounds
(
font
.
Bounds
(
fupe
))
fmt
.
Printf
(
"FUnitsPerEm:%d
\n\n
"
,
fupe
)
...
...
freetype.go
浏览文件 @
2a5cbfd4
...
...
@@ -78,15 +78,15 @@ type Context struct {
// 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
scale
fixed
.
Int26_6
hinting
Hinting
// cache is the glyph cache.
cache
[
nGlyphs
*
nXFractions
*
nYFractions
]
cacheEntry
}
// PointToFix
32
converts the given number of points (as in ``a 12 point font'')
// into
fixed point unit
s.
func
(
c
*
Context
)
PointToFix
32
(
x
float64
)
fixed
.
Int26_6
{
// PointToFix
ed
converts the given number of points (as in ``a 12 point font'')
// into
a 26.6 fixed point number of pixel
s.
func
(
c
*
Context
)
PointToFix
ed
(
x
float64
)
fixed
.
Int26_6
{
return
fixed
.
Int26_6
(
x
*
float64
(
c
.
dpi
)
*
(
64.0
/
72.0
))
}
...
...
@@ -269,7 +269,7 @@ func (c *Context) DrawString(s string, p fixed.Point26_6) (fixed.Point26_6, erro
// 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
))
c
.
scale
=
fixed
.
Int26_6
(
c
.
fontSize
*
c
.
dpi
*
(
64.0
/
72.0
))
if
c
.
font
==
nil
{
c
.
r
.
SetBounds
(
0
,
0
)
}
else
{
...
...
truetype/glyph.go
浏览文件 @
2a5cbfd4
...
...
@@ -5,8 +5,12 @@
package
truetype
import
(
"golang.org/x/image/math/fixed"
)
// Hinting is the policy for snapping a glyph's contours to pixel boundaries.
type
Hinting
int32
type
Hinting
u
int32
const
(
// NoHinting means to not perform any hinting.
...
...
@@ -20,7 +24,7 @@ const (
// 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
X
,
Y
fixed
.
Int26_6
// The Flags' LSB means whether or not this Point is ``on'' the contour.
// Other bits are reserved for internal use.
Flags
uint32
...
...
@@ -30,7 +34,7 @@ type Point struct {
// series of glyphs from a Font.
type
GlyphBuf
struct
{
// AdvanceWidth is the glyph's advance width.
AdvanceWidth
int32
AdvanceWidth
fixed
.
Int26_6
// B is the glyph's bounding box.
B
Bounds
// Point contains all Points from all contours of the glyph. If
...
...
@@ -45,7 +49,7 @@ type GlyphBuf struct {
End
[]
int
font
*
Font
scale
int32
scale
fixed
.
Int26_6
hinting
Hinting
hinter
hinter
// phantomPoints are the co-ordinates of the synthetic phantom points
...
...
@@ -54,7 +58,7 @@ type GlyphBuf struct {
// 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
pp1x
fixed
.
Int26_6
// 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
...
...
@@ -84,10 +88,10 @@ const (
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
{
// 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
fixed
.
Int26_6
,
i
Index
,
h
Hinting
)
error
{
g
.
Point
=
g
.
Point
[
:
0
]
g
.
Unhinted
=
g
.
Unhinted
[
:
0
]
g
.
InFontUnits
=
g
.
InFontUnits
[
:
0
]
...
...
@@ -125,8 +129,8 @@ func (g *GlyphBuf) Load(f *Font, scale int32, i Index, h Hinting) error {
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
if
fixed
.
Int26_6
(
hdmx
[
0
])
==
scale
>>
6
{
advanceWidth
=
fixed
.
Int26_6
(
hdmx
[
2
+
i
])
<<
6
break
}
}
...
...
@@ -175,7 +179,7 @@ func (g *GlyphBuf) Load(f *Font, scale int32, i Index, h Hinting) error {
return
nil
}
func
(
g
*
GlyphBuf
)
load
(
recursion
int32
,
i
Index
,
useMyMetrics
bool
)
(
err
error
)
{
func
(
g
*
GlyphBuf
)
load
(
recursion
u
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"
)
...
...
@@ -193,16 +197,16 @@ func (g *GlyphBuf) load(recursion int32, i Index, useMyMetrics bool) (err error)
// 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
)
glyf
,
ne
,
boundsXMin
,
boundsYMax
:=
[]
byte
(
nil
),
0
,
fixed
.
Int26_6
(
0
),
fixed
.
Int26_6
(
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
)))
boundsXMin
=
fixed
.
Int26_6
(
int16
(
u16
(
glyf
,
2
)))
boundsYMax
=
fixed
.
Int26_6
(
int16
(
u16
(
glyf
,
8
)))
}
// Create the phantom points.
uhm
,
pp1x
:=
g
.
font
.
unscaledHMetric
(
i
),
int32
(
0
)
uhm
,
pp1x
:=
g
.
font
.
unscaledHMetric
(
i
),
fixed
.
Int26_6
(
0
)
uvm
:=
g
.
font
.
unscaledVMetric
(
i
,
boundsYMax
)
g
.
phantomPoints
=
[
4
]
Point
{
{
X
:
boundsXMin
-
uhm
.
LeftSideBearing
},
...
...
@@ -322,7 +326,7 @@ func (g *GlyphBuf) loadSimple(glyf []byte, ne int) (program []byte) {
x
+=
int16
(
u16
(
glyf
,
offset
))
offset
+=
2
}
g
.
Point
[
i
]
.
X
=
int32
(
x
)
g
.
Point
[
i
]
.
X
=
fixed
.
Int26_6
(
x
)
}
var
y
int16
for
i
:=
np0
;
i
<
np1
;
i
++
{
...
...
@@ -339,13 +343,13 @@ func (g *GlyphBuf) loadSimple(glyf []byte, ne int) (program []byte) {
y
+=
int16
(
u16
(
glyf
,
offset
))
offset
+=
2
}
g
.
Point
[
i
]
.
Y
=
int32
(
y
)
g
.
Point
[
i
]
.
Y
=
fixed
.
Int26_6
(
y
)
}
return
program
}
func
(
g
*
GlyphBuf
)
loadCompound
(
recursion
int32
,
uhm
HMetric
,
i
Index
,
func
(
g
*
GlyphBuf
)
loadCompound
(
recursion
u
int32
,
uhm
HMetric
,
i
Index
,
glyf
[]
byte
,
useMyMetrics
bool
)
error
{
// Flags for decoding a compound glyph. These flags are documented at
...
...
@@ -368,14 +372,14 @@ func (g *GlyphBuf) loadCompound(recursion int32, uhm HMetric, i Index,
for
{
flags
:=
u16
(
glyf
,
offset
)
component
:=
Index
(
u16
(
glyf
,
offset
+
2
))
dx
,
dy
,
transform
,
hasTransform
:=
int32
(
0
),
int32
(
0
),
[
4
]
int32
{},
false
dx
,
dy
,
transform
,
hasTransform
:=
fixed
.
Int26_6
(
0
),
fixed
.
Int26_6
(
0
),
[
4
]
int16
{},
false
if
flags
&
flagArg1And2AreWords
!=
0
{
dx
=
int32
(
int16
(
u16
(
glyf
,
offset
+
4
)))
dy
=
int32
(
int16
(
u16
(
glyf
,
offset
+
6
)))
dx
=
fixed
.
Int26_6
(
int16
(
u16
(
glyf
,
offset
+
4
)))
dy
=
fixed
.
Int26_6
(
int16
(
u16
(
glyf
,
offset
+
6
)))
offset
+=
8
}
else
{
dx
=
int32
(
int16
(
int8
(
glyf
[
offset
+
4
])))
dy
=
int32
(
int16
(
int8
(
glyf
[
offset
+
5
])))
dx
=
fixed
.
Int26_6
(
int16
(
int8
(
glyf
[
offset
+
4
])))
dy
=
fixed
.
Int26_6
(
int16
(
int8
(
glyf
[
offset
+
5
])))
offset
+=
6
}
if
flags
&
flagArgsAreXYValues
==
0
{
...
...
@@ -385,18 +389,18 @@ func (g *GlyphBuf) loadCompound(recursion int32, uhm HMetric, i Index,
hasTransform
=
true
switch
{
case
flags
&
flagWeHaveAScale
!=
0
:
transform
[
0
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
0
)
))
transform
[
0
]
=
int
16
(
u16
(
glyf
,
offset
+
0
))
transform
[
3
]
=
transform
[
0
]
offset
+=
2
case
flags
&
flagWeHaveAnXAndYScale
!=
0
:
transform
[
0
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
0
)
))
transform
[
3
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
2
)
))
transform
[
0
]
=
int
16
(
u16
(
glyf
,
offset
+
0
))
transform
[
3
]
=
int
16
(
u16
(
glyf
,
offset
+
2
))
offset
+=
4
case
flags
&
flagWeHaveATwoByTwo
!=
0
:
transform
[
0
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
0
)
))
transform
[
1
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
2
)
))
transform
[
2
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
4
)
))
transform
[
3
]
=
int
32
(
int16
(
u16
(
glyf
,
offset
+
6
)
))
transform
[
0
]
=
int
16
(
u16
(
glyf
,
offset
+
0
))
transform
[
1
]
=
int
16
(
u16
(
glyf
,
offset
+
2
))
transform
[
2
]
=
int
16
(
u16
(
glyf
,
offset
+
4
))
transform
[
3
]
=
int
16
(
u16
(
glyf
,
offset
+
6
))
offset
+=
8
}
}
...
...
@@ -412,10 +416,12 @@ func (g *GlyphBuf) loadCompound(recursion int32, uhm HMetric, i Index,
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
)
newX
:=
0
+
fixed
.
Int26_6
((
int64
(
p
.
X
)
*
int64
(
transform
[
0
])
+
1
<<
13
)
>>
14
)
+
fixed
.
Int26_6
((
int64
(
p
.
Y
)
*
int64
(
transform
[
2
])
+
1
<<
13
)
>>
14
)
newY
:=
0
+
fixed
.
Int26_6
((
int64
(
p
.
X
)
*
int64
(
transform
[
1
])
+
1
<<
13
)
>>
14
)
+
fixed
.
Int26_6
((
int64
(
p
.
Y
)
*
int64
(
transform
[
3
])
+
1
<<
13
)
>>
14
)
p
.
X
,
p
.
Y
=
newX
,
newY
}
}
...
...
truetype/hint.go
浏览文件 @
2a5cbfd4
...
...
@@ -11,6 +11,8 @@ package truetype
import
(
"errors"
"math"
"golang.org/x/image/math/fixed"
)
const
(
...
...
@@ -47,7 +49,7 @@ type hinter struct {
// Changing the font will require running the new font's fpgm bytecode.
// Changing either will require running the font's prep bytecode.
font
*
Font
scale
int32
scale
fixed
.
Int26_6
// gs and defaultGS are the current and default graphics state. The
// default graphics state is the global default graphics state after
...
...
@@ -113,7 +115,7 @@ func resetTwilightPoints(f *Font, p []Point) []Point {
return
p
}
func
(
h
*
hinter
)
init
(
f
*
Font
,
scale
int32
)
error
{
func
(
h
*
hinter
)
init
(
f
*
Font
,
scale
fixed
.
Int26_6
)
error
{
h
.
points
[
twilightZone
][
0
]
=
resetTwilightPoints
(
f
,
h
.
points
[
twilightZone
][
0
])
h
.
points
[
twilightZone
][
1
]
=
resetTwilightPoints
(
f
,
h
.
points
[
twilightZone
][
1
])
h
.
points
[
twilightZone
][
2
]
=
resetTwilightPoints
(
f
,
h
.
points
[
twilightZone
][
2
])
...
...
@@ -315,8 +317,8 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
mulDiv
(
int64
(
dy
),
int64
(
dbx
),
0x40
)
rx
:=
mulDiv
(
val
,
int64
(
dax
),
discriminant
)
ry
:=
mulDiv
(
val
,
int64
(
day
),
discriminant
)
p
.
X
=
a0
.
X
+
int32
(
rx
)
p
.
Y
=
a0
.
Y
+
int32
(
ry
)
p
.
X
=
a0
.
X
+
fixed
.
Int26_6
(
rx
)
p
.
Y
=
a0
.
Y
+
fixed
.
Int26_6
(
ry
)
}
else
{
p
.
X
=
(
a0
.
X
+
a1
.
X
+
b0
.
X
+
b1
.
X
)
/
4
p
.
Y
=
(
a0
.
Y
+
a1
.
Y
+
b0
.
Y
+
b1
.
Y
)
/
4
...
...
@@ -379,7 +381,7 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
case
opSSW
:
top
--
h
.
gs
.
singleWidth
=
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
h
.
stack
[
top
]
))
h
.
gs
.
singleWidth
=
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
fixed
.
Int26_6
(
h
.
stack
[
top
])
))
case
opDUP
:
if
top
>=
len
(
h
.
stack
)
{
...
...
@@ -711,8 +713,8 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
if
h
.
gs
.
zp
[
0
]
==
0
{
p
:=
h
.
point
(
0
,
unhinted
,
i
)
q
:=
h
.
point
(
0
,
current
,
i
)
p
.
X
=
int32
((
int64
(
distance
)
*
int64
(
h
.
gs
.
fv
[
0
]))
>>
14
)
p
.
Y
=
int32
((
int64
(
distance
)
*
int64
(
h
.
gs
.
fv
[
1
]))
>>
14
)
p
.
X
=
fixed
.
Int26_6
((
int64
(
distance
)
*
int64
(
h
.
gs
.
fv
[
0
]))
>>
14
)
p
.
Y
=
fixed
.
Int26_6
((
int64
(
distance
)
*
int64
(
h
.
gs
.
fv
[
1
]))
>>
14
)
*
q
=
*
p
}
p
:=
h
.
point
(
0
,
current
,
i
)
...
...
@@ -809,7 +811,7 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
}
d
:=
int32
(
dotProduct
(
f26dot6
(
p
.
X
-
q
.
X
),
f26dot6
(
p
.
Y
-
q
.
Y
),
v
))
if
scale
{
d
=
int32
(
int64
(
d
*
h
.
scale
)
/
int64
(
h
.
font
.
fUnitsPerEm
))
d
=
int32
(
int64
(
d
*
int32
(
h
.
scale
)
)
/
int64
(
h
.
font
.
fUnitsPerEm
))
}
h
.
stack
[
top
-
1
]
=
d
...
...
@@ -818,7 +820,7 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
return
errors
.
New
(
"truetype: hinting: stack overflow"
)
}
// For MPS, point size should be irrelevant; we return the PPEM.
h
.
stack
[
top
]
=
h
.
scale
>>
6
h
.
stack
[
top
]
=
int32
(
h
.
scale
)
>>
6
top
++
case
opFLIPON
,
opFLIPOFF
:
...
...
@@ -935,7 +937,7 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
case
opWCVTF
:
top
-=
2
h
.
setScaledCVT
(
h
.
stack
[
top
],
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
h
.
stack
[
top
+
1
]
)))
h
.
setScaledCVT
(
h
.
stack
[
top
],
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
fixed
.
Int26_6
(
h
.
stack
[
top
+
1
])
)))
case
opDELTAP2
,
opDELTAP3
,
opDELTAC1
,
opDELTAC2
,
opDELTAC3
:
goto
delta
...
...
@@ -1144,7 +1146,7 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
p0
:=
h
.
point
(
1
,
inFontUnits
,
i
)
p1
:=
h
.
point
(
0
,
inFontUnits
,
h
.
gs
.
rp
[
0
])
oldDist
=
dotProduct
(
f26dot6
(
p0
.
X
-
p1
.
X
),
f26dot6
(
p0
.
Y
-
p1
.
Y
),
h
.
gs
.
dv
)
oldDist
=
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
int32
(
oldDist
)))
oldDist
=
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
fixed
.
Int26_6
(
oldDist
)))
}
// Single-width cut-in test.
...
...
@@ -1358,7 +1360,7 @@ func (h *hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
c
+=
32
}
c
+=
h
.
gs
.
deltaBase
if
ppem
:=
(
h
.
scale
+
1
<<
5
)
>>
6
;
ppem
!=
c
{
if
ppem
:=
(
int32
(
h
.
scale
)
+
1
<<
5
)
>>
6
;
ppem
!=
c
{
continue
}
b
=
(
b
&
0x0f
)
-
8
...
...
@@ -1399,7 +1401,7 @@ func (h *hinter) initializeScaledCVT() {
}
for
i
:=
range
h
.
scaledCVT
{
unscaled
:=
uint16
(
h
.
font
.
cvt
[
2
*
i
])
<<
8
|
uint16
(
h
.
font
.
cvt
[
2
*
i
+
1
])
h
.
scaledCVT
[
i
]
=
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
int32
(
int16
(
unscaled
))))
h
.
scaledCVT
[
i
]
=
f26dot6
(
h
.
font
.
scale
(
h
.
scale
*
fixed
.
Int26_6
(
int16
(
unscaled
))))
}
}
...
...
@@ -1437,7 +1439,7 @@ func (h *hinter) move(p *Point, distance f26dot6, touch bool) {
fvx
:=
int64
(
h
.
gs
.
fv
[
0
])
pvx
:=
int64
(
h
.
gs
.
pv
[
0
])
if
fvx
==
0x4000
&&
pvx
==
0x4000
{
p
.
X
+=
int32
(
distance
)
p
.
X
+=
fixed
.
Int26_6
(
distance
)
if
touch
{
p
.
Flags
|=
flagTouchedX
}
...
...
@@ -1447,7 +1449,7 @@ func (h *hinter) move(p *Point, distance f26dot6, touch bool) {
fvy
:=
int64
(
h
.
gs
.
fv
[
1
])
pvy
:=
int64
(
h
.
gs
.
pv
[
1
])
if
fvy
==
0x4000
&&
pvy
==
0x4000
{
p
.
Y
+=
int32
(
distance
)
p
.
Y
+=
fixed
.
Int26_6
(
distance
)
if
touch
{
p
.
Flags
|=
flagTouchedY
}
...
...
@@ -1457,14 +1459,14 @@ func (h *hinter) move(p *Point, distance f26dot6, touch bool) {
fvDotPv
:=
(
fvx
*
pvx
+
fvy
*
pvy
)
>>
14
if
fvx
!=
0
{
p
.
X
+=
int32
(
mulDiv
(
fvx
,
int64
(
distance
),
fvDotPv
))
p
.
X
+=
fixed
.
Int26_6
(
mulDiv
(
fvx
,
int64
(
distance
),
fvDotPv
))
if
touch
{
p
.
Flags
|=
flagTouchedX
}
}
if
fvy
!=
0
{
p
.
Y
+=
int32
(
mulDiv
(
fvy
,
int64
(
distance
),
fvDotPv
))
p
.
Y
+=
fixed
.
Int26_6
(
mulDiv
(
fvy
,
int64
(
distance
),
fvDotPv
))
if
touch
{
p
.
Flags
|=
flagTouchedY
}
...
...
@@ -1480,7 +1482,7 @@ func (h *hinter) iupInterp(interpY bool, p1, p2, ref1, ref2 int) {
return
}
var
ifu1
,
ifu2
int32
var
ifu1
,
ifu2
fixed
.
Int26_6
if
interpY
{
ifu1
=
h
.
points
[
glyphZone
][
inFontUnits
][
ref1
]
.
Y
ifu2
=
h
.
points
[
glyphZone
][
inFontUnits
][
ref2
]
.
Y
...
...
@@ -1493,7 +1495,7 @@ func (h *hinter) iupInterp(interpY bool, p1, p2, ref1, ref2 int) {
ref1
,
ref2
=
ref2
,
ref1
}
var
unh1
,
unh2
,
delta1
,
delta2
int32
var
unh1
,
unh2
,
delta1
,
delta2
fixed
.
Int26_6
if
interpY
{
unh1
=
h
.
points
[
glyphZone
][
unhinted
][
ref1
]
.
Y
unh2
=
h
.
points
[
glyphZone
][
unhinted
][
ref2
]
.
Y
...
...
@@ -1506,7 +1508,7 @@ func (h *hinter) iupInterp(interpY bool, p1, p2, ref1, ref2 int) {
delta2
=
h
.
points
[
glyphZone
][
current
][
ref2
]
.
X
-
unh2
}
var
xy
,
ifuXY
int32
var
xy
,
ifuXY
fixed
.
Int26_6
if
ifu1
==
ifu2
{
for
i
:=
p1
;
i
<=
p2
;
i
++
{
if
interpY
{
...
...
@@ -1555,7 +1557,7 @@ func (h *hinter) iupInterp(interpY bool, p1, p2, ref1, ref2 int) {
}
else
{
numer
-=
0x8000
}
xy
=
unh1
+
delta1
+
int32
(
numer
/
0x10000
)
xy
=
unh1
+
delta1
+
fixed
.
Int26_6
(
numer
/
0x10000
)
}
if
interpY
{
...
...
@@ -1567,7 +1569,7 @@ func (h *hinter) iupInterp(interpY bool, p1, p2, ref1, ref2 int) {
}
func
(
h
*
hinter
)
iupShift
(
interpY
bool
,
p1
,
p2
,
p
int
)
{
var
delta
int32
var
delta
fixed
.
Int26_6
if
interpY
{
delta
=
h
.
points
[
glyphZone
][
current
][
p
]
.
Y
-
h
.
points
[
glyphZone
][
unhinted
][
p
]
.
Y
}
else
{
...
...
truetype/hint_test.go
浏览文件 @
2a5cbfd4
...
...
@@ -9,6 +9,8 @@ import (
"reflect"
"strings"
"testing"
"golang.org/x/image/math/fixed"
)
func
TestBytecode
(
t
*
testing
.
T
)
{
...
...
@@ -589,7 +591,7 @@ func TestMove(t *testing.T) {
h
,
p
:=
hinter
{},
Point
{}
testCases
:=
[]
struct
{
pvX
,
pvY
,
fvX
,
fvY
f2dot14
wantX
,
wantY
int32
wantX
,
wantY
fixed
.
Int26_6
}{
{
+
0x4000
,
+
0x0000
,
+
0x4000
,
+
0x0000
,
+
1000
,
+
0
},
{
+
0x4000
,
+
0x0000
,
-
0x4000
,
+
0x0000
,
+
1000
,
+
0
},
...
...
truetype/truetype.go
浏览文件 @
2a5cbfd4
...
...
@@ -9,10 +9,9 @@
//
// 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.
// is the number of pixels in 1 em, expressed as a 26.6 fixed point value. For
// example, if 1 em is 10 pixels then scale is fixed.I(10), which is equal to
// fixed.Int26_6(10 << 6).
//
// To measure a TrueType font in ideal FUnit space, use scale equal to
// font.FUnitsPerEm().
...
...
@@ -20,6 +19,8 @@ package truetype // import "github.com/golang/freetype/truetype"
import
(
"fmt"
"golang.org/x/image/math/fixed"
)
// An Index is a Font's index of a rune.
...
...
@@ -28,17 +29,17 @@ 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
XMin
,
YMin
,
XMax
,
YMax
fixed
.
Int26_6
}
// An HMetric holds the horizontal metrics of a single glyph.
type
HMetric
struct
{
AdvanceWidth
,
LeftSideBearing
int32
AdvanceWidth
,
LeftSideBearing
fixed
.
Int26_6
}
// A VMetric holds the vertical metrics of a single glyph.
type
VMetric
struct
{
AdvanceHeight
,
TopSideBearing
int32
AdvanceHeight
,
TopSideBearing
fixed
.
Int26_6
}
// A FormatError reports that the input is not a valid TrueType font.
...
...
@@ -226,10 +227,10 @@ func (f *Font) parseHead() error {
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
)))
f
.
bounds
.
XMin
=
fixed
.
Int26_6
(
int16
(
u16
(
f
.
head
,
36
)))
f
.
bounds
.
YMin
=
fixed
.
Int26_6
(
int16
(
u16
(
f
.
head
,
38
)))
f
.
bounds
.
XMax
=
fixed
.
Int26_6
(
int16
(
u16
(
f
.
head
,
40
)))
f
.
bounds
.
YMax
=
fixed
.
Int26_6
(
int16
(
u16
(
f
.
head
,
42
)))
switch
i
:=
u16
(
f
.
head
,
50
);
i
{
case
0
:
f
.
locaOffsetFormat
=
locaOffsetFormatShort
...
...
@@ -306,17 +307,17 @@ func (f *Font) parseMaxp() error {
}
// scale returns x divided by f.fUnitsPerEm, rounded to the nearest integer.
func
(
f
*
Font
)
scale
(
x
int32
)
int32
{
func
(
f
*
Font
)
scale
(
x
fixed
.
Int26_6
)
fixed
.
Int26_6
{
if
x
>=
0
{
x
+=
f
.
fUnitsPerEm
/
2
x
+=
f
ixed
.
Int26_6
(
f
.
fUnitsPerEm
)
/
2
}
else
{
x
-=
f
.
fUnitsPerEm
/
2
x
-=
f
ixed
.
Int26_6
(
f
.
fUnitsPerEm
)
/
2
}
return
x
/
f
.
fUnitsPerEm
return
x
/
f
ixed
.
Int26_6
(
f
.
fUnitsPerEm
)
}
// Bounds returns the union of a Font's glyphs' bounds.
func
(
f
*
Font
)
Bounds
(
scale
int32
)
Bounds
{
func
(
f
*
Font
)
Bounds
(
scale
fixed
.
Int26_6
)
Bounds
{
b
:=
f
.
bounds
b
.
XMin
=
f
.
scale
(
scale
*
b
.
XMin
)
b
.
YMin
=
f
.
scale
(
scale
*
b
.
YMin
)
...
...
@@ -360,18 +361,18 @@ func (f *Font) unscaledHMetric(i Index) (h 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
))),
AdvanceWidth
:
fixed
.
Int26_6
(
u16
(
f
.
hmtx
,
p
)),
LeftSideBearing
:
fixed
.
Int26_6
(
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
))),
AdvanceWidth
:
fixed
.
Int26_6
(
u16
(
f
.
hmtx
,
4
*
j
)),
LeftSideBearing
:
fixed
.
Int26_6
(
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
{
func
(
f
*
Font
)
HMetric
(
scale
fixed
.
Int26_6
,
i
Index
)
HMetric
{
h
:=
f
.
unscaledHMetric
(
i
)
h
.
AdvanceWidth
=
f
.
scale
(
scale
*
h
.
AdvanceWidth
)
h
.
LeftSideBearing
=
f
.
scale
(
scale
*
h
.
LeftSideBearing
)
...
...
@@ -380,15 +381,15 @@ func (f *Font) HMetric(scale int32, i Index) HMetric {
// 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
)
{
func
(
f
*
Font
)
unscaledVMetric
(
i
Index
,
yMax
fixed
.
Int26_6
)
(
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
))),
AdvanceHeight
:
fixed
.
Int26_6
(
u16
(
f
.
vmtx
,
4
*
j
)),
TopSideBearing
:
fixed
.
Int26_6
(
int16
(
u16
(
f
.
vmtx
,
4
*
j
+
2
))),
}
}
// The OS/2 table has grown over time.
...
...
@@ -397,21 +398,21 @@ func (f *Font) unscaledVMetric(i Index, yMax int32) (v VMetric) {
// 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
)))
sTypoAscender
:=
fixed
.
Int26_6
(
int16
(
u16
(
f
.
os2
,
68
)))
sTypoDescender
:=
fixed
.
Int26_6
(
int16
(
u16
(
f
.
os2
,
70
)))
return
VMetric
{
AdvanceHeight
:
sTypoAscender
-
sTypoDescender
,
TopSideBearing
:
sTypoAscender
-
yMax
,
}
}
return
VMetric
{
AdvanceHeight
:
f
.
fUnitsPerEm
,
AdvanceHeight
:
f
ixed
.
Int26_6
(
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
{
func
(
f
*
Font
)
VMetric
(
scale
fixed
.
Int26_6
,
i
Index
)
VMetric
{
// TODO: should 0 be bounds.YMax?
v
:=
f
.
unscaledVMetric
(
i
,
0
)
v
.
AdvanceHeight
=
f
.
scale
(
scale
*
v
.
AdvanceHeight
)
...
...
@@ -420,7 +421,7 @@ func (f *Font) VMetric(scale int32, i Index) VMetric {
}
// Kerning returns the kerning for the given glyph pair.
func
(
f
*
Font
)
Kerning
(
scale
int32
,
i0
,
i1
Index
)
int32
{
func
(
f
*
Font
)
Kerning
(
scale
fixed
.
Int26_6
,
i0
,
i1
Index
)
fixed
.
Int26_6
{
if
f
.
nKern
==
0
{
return
0
}
...
...
@@ -434,7 +435,7 @@ func (f *Font) Kerning(scale int32, i0, i1 Index) int32 {
}
else
if
ig
>
g
{
hi
=
i
}
else
{
return
f
.
scale
(
scale
*
int32
(
int16
(
u16
(
f
.
kern
,
22
+
6
*
i
))))
return
f
.
scale
(
scale
*
fixed
.
Int26_6
(
int16
(
u16
(
f
.
kern
,
22
+
6
*
i
))))
}
}
return
0
...
...
truetype/truetype_test.go
浏览文件 @
2a5cbfd4
...
...
@@ -14,6 +14,8 @@ import (
"strconv"
"strings"
"testing"
"golang.org/x/image/math/fixed"
)
func
parseTestdataFont
(
name
string
)
(
font
*
Font
,
testdataIsOptional
bool
,
err
error
)
{
...
...
@@ -40,7 +42,7 @@ func TestParse(t *testing.T) {
if
got
,
want
:=
font
.
FUnitsPerEm
(),
int32
(
2048
);
got
!=
want
{
t
.
Errorf
(
"FUnitsPerEm: got %v, want %v"
,
got
,
want
)
}
fupe
:=
f
ont
.
FUnitsPerEm
(
)
fupe
:=
f
ixed
.
Int26_6
(
font
.
FUnitsPerEm
()
)
if
got
,
want
:=
font
.
Bounds
(
fupe
),
(
Bounds
{
-
441
,
-
432
,
2024
,
2033
});
got
!=
want
{
t
.
Errorf
(
"Bounds: got %v, want %v"
,
got
,
want
)
}
...
...
@@ -56,7 +58,7 @@ func TestParse(t *testing.T) {
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
{
if
got
,
want
:=
font
.
Kerning
(
fupe
,
i0
,
i1
),
fixed
.
Int26_6
(
-
144
);
got
!=
want
{
t
.
Errorf
(
"Kerning: got %v, want %v"
,
got
,
want
)
}
...
...
@@ -196,7 +198,7 @@ func TestIndex(t *testing.T) {
}
type
scalingTestData
struct
{
advanceWidth
int32
advanceWidth
fixed
.
Int26_6
bounds
Bounds
points
[]
Point
}
...
...
@@ -205,13 +207,13 @@ type scalingTestData struct {
// 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
)
{
next
:=
func
(
s
string
)
(
string
,
fixed
.
Int26_6
)
{
t
,
i
:=
""
,
strings
.
Index
(
s
,
" "
)
if
i
!=
-
1
{
s
,
t
=
s
[
:
i
],
s
[
i
+
1
:
]
}
x
,
_
:=
strconv
.
Atoi
(
s
)
return
t
,
int32
(
x
)
return
t
,
fixed
.
Int26_6
(
x
)
}
i
:=
strings
.
Index
(
line
,
";"
)
...
...
@@ -257,7 +259,7 @@ func scalingTestEquals(a, b []Point) (index int, equals bool) {
var
scalingTestCases
=
[]
struct
{
name
string
size
int
32
size
int
}{
{
"luxisr"
,
12
},
{
"x-arial-bold"
,
11
},
...
...
@@ -318,7 +320,7 @@ func testScaling(t *testing.T, h Hinting) {
glyphBuf
:=
NewGlyphBuf
()
for
i
,
want
:=
range
wants
{
if
err
=
glyphBuf
.
Load
(
font
,
tc
.
size
*
64
,
Index
(
i
),
h
);
err
!=
nil
{
if
err
=
glyphBuf
.
Load
(
font
,
fixed
.
I
(
tc
.
size
)
,
Index
(
i
),
h
);
err
!=
nil
{
t
.
Errorf
(
"%s: glyph #%d: Load: %v"
,
tc
.
name
,
i
,
err
)
continue
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录