Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小雨青年
freetype
提交
0a778f7f
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,发现更多精彩内容 >>
提交
0a778f7f
编写于
10月 11, 2013
作者:
N
Nigel Tao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
freetype/truetype: parse UCS-4 encoded cmap tables.
R=bsiegert CC=golang-dev
https://codereview.appspot.com/14548046
上级
ba07cbfb
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
182 addition
and
53 deletion
+182
-53
freetype/truetype/truetype.go
freetype/truetype/truetype.go
+63
-36
freetype/truetype/truetype_test.go
freetype/truetype/truetype_test.go
+119
-17
未找到文件。
freetype/truetype/truetype.go
浏览文件 @
0a778f7f
...
...
@@ -87,7 +87,7 @@ const (
// A cm holds a parsed cmap entry.
type
cm
struct
{
start
,
end
,
delta
,
offset
uint
16
start
,
end
,
delta
,
offset
uint
32
}
// A Font represents a Truetype font.
...
...
@@ -111,12 +111,14 @@ type Font struct {
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.
unicodeEncoding
=
0x00000003
// PID = 0 (Unicode), PSID = 3 (Unicode 2.0)
microsoftEncoding
=
0x00030001
// PID = 3 (Microsoft), PSID = 1 (UCS-2)
unicodeEncoding
=
0x00000003
// PID = 0 (Unicode), PSID = 3 (Unicode 2.0)
microsoftUCS2Encoding
=
0x00030001
// PID = 3 (Microsoft), PSID = 1 (UCS-2)
microsoftUCS4Encoding
=
0x0003000a
// PID = 3 (Microsoft), PSID = 10 (UCS-4)
)
if
len
(
f
.
cmap
)
<
4
{
...
...
@@ -137,7 +139,7 @@ func (f *Font) parseCmap() error {
if
pidPsid
==
unicodeEncoding
{
offset
,
found
=
int
(
o
),
true
break
}
else
if
pidPsid
==
microsoftEncoding
{
}
else
if
pidPsid
==
microsoft
UCS2Encoding
||
pidPsid
==
microsoftUCS4
Encoding
{
offset
,
found
=
int
(
o
),
true
// We don't break out of the for loop, so that Unicode can override Microsoft.
}
...
...
@@ -150,39 +152,63 @@ func (f *Font) parseCmap() error {
}
cmapFormat
:=
u16
(
f
.
cmap
,
offset
)
if
cmapFormat
!=
cmapFormat4
{
return
UnsupportedError
(
fmt
.
Sprintf
(
"cmap format: %d"
,
cmapFormat
))
}
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
=
u16
(
f
.
cmap
,
offset
)
offset
+=
2
}
offset
+=
2
for
i
:=
0
;
i
<
segCount
;
i
++
{
f
.
cm
[
i
]
.
start
=
u16
(
f
.
cmap
,
offset
)
offset
+=
2
}
for
i
:=
0
;
i
<
segCount
;
i
++
{
f
.
cm
[
i
]
.
delta
=
u16
(
f
.
cmap
,
offset
)
offset
+=
2
}
for
i
:=
0
;
i
<
segCount
;
i
++
{
f
.
cm
[
i
]
.
offset
=
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
}
f
.
cmapIndexes
=
f
.
cmap
[
offset
:
]
return
nil
return
UnsupportedError
(
fmt
.
Sprintf
(
"cmap format: %d"
,
cmapFormat
))
}
func
(
f
*
Font
)
parseHead
()
error
{
...
...
@@ -296,8 +322,9 @@ func (f *Font) FUnitsPerEm() int32 {
// Index returns a Font's index for the given rune.
func
(
f
*
Font
)
Index
(
x
rune
)
Index
{
c
:=
uint
16
(
x
)
c
:=
uint
32
(
x
)
n
:=
len
(
f
.
cm
)
// TODO: binary search.
for
i
:=
0
;
i
<
n
;
i
++
{
if
f
.
cm
[
i
]
.
start
<=
c
&&
c
<=
f
.
cm
[
i
]
.
end
{
if
f
.
cm
[
i
]
.
offset
==
0
{
...
...
freetype/truetype/truetype_test.go
浏览文件 @
0a778f7f
...
...
@@ -16,14 +16,24 @@ import (
"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
)
{
b
,
err
:=
ioutil
.
ReadFile
(
"../../testdata/luxisr.ttf"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
font
,
err
:=
Parse
(
b
)
font
,
_
,
err
:=
parseTestdataFont
(
"luxisr"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
...
...
@@ -74,6 +84,105 @@ func TestParse(t *testing.T) {
}
}
func
TestIndex
(
t
*
testing
.
T
)
{
testCases
:=
map
[
string
]
map
[
rune
]
Index
{
"luxisr"
:
{
' '
:
3
,
'!'
:
4
,
'A'
:
36
,
'V'
:
57
,
'É'
:
101
,
'fl'
:
193
,
'\u22c5'
:
385
,
'中'
:
0
,
},
"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
,
'⊕'
:
3109
,
'fl'
:
4560
,
'\ufb03'
:
4561
,
'\ufffd'
:
4645
,
// 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(%q): got %d, want %d"
,
name
,
r
,
got
,
want
)
}
}
}
}
var
scalingTestCases
=
[]
struct
{
name
string
size
int32
...
...
@@ -87,29 +196,22 @@ var scalingTestCases = []struct {
// GlyphBuf.Load, and the unhinted values match C Freetype.
{
"x-arial-bold"
,
11
,
0
},
//{"x-deja-vu-sans-oblique", 17, 0},
//
{"x-droid-sans-japanese", 9, 0},
{
"x-droid-sans-japanese"
,
9
,
0
},
//{"x-times-new-roman", 13, 0},
}
func
testScaling
(
t
*
testing
.
T
,
hinter
*
Hinter
)
{
loop
:
for
_
,
tc
:=
range
scalingTestCases
{
b
,
err
:=
ioutil
.
ReadFile
(
fmt
.
Sprintf
(
"../../testdata/%s.ttf"
,
tc
.
name
)
)
font
,
testdataIsOptional
,
err
:=
parseTestdataFont
(
tc
.
name
)
if
err
!=
nil
{
// The "x-foo" fonts are optional tests, as they are not checked
// in for copyright or file size reasons.
if
strings
.
HasPrefix
(
tc
.
name
,
"x-"
)
{
t
.
Logf
(
"%s: ReadFile: %v"
,
tc
.
name
,
err
)
if
testdataIsOptional
{
t
.
Log
(
err
)
}
else
{
t
.
Error
f
(
"%s: ReadFile: %v"
,
tc
.
name
,
err
)
t
.
Error
(
err
)
}
continue
loop
}
font
,
err
:=
Parse
(
b
)
if
err
!=
nil
{
t
.
Errorf
(
"%s: Parse: %v"
,
tc
.
name
,
err
)
continue
loop
}
hinting
:=
"sans"
if
hinter
!=
nil
{
hinting
=
"with"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录