Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Harfbuzz
提交
205737ac
T
Third Party Harfbuzz
项目概览
OpenHarmony
/
Third Party Harfbuzz
接近 2 年 前同步成功
通知
1
Star
18
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
Third Party Harfbuzz
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
205737ac
编写于
10月 12, 2018
作者:
D
David Corbett
提交者:
Behdad Esfahbod
10月 23, 2018
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[use] Prohibit visually ambiguous vowel sequences
上级
48ed598a
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
827 addition
and
274 deletion
+827
-274
src/Makefile.am
src/Makefile.am
+6
-1
src/Makefile.sources
src/Makefile.sources
+1
-0
src/gen-vowel-constraints.py
src/gen-vowel-constraints.py
+286
-0
src/hb-ot-shape-complex-indic.cc
src/hb-ot-shape-complex-indic.cc
+2
-270
src/hb-ot-shape-complex-use.cc
src/hb-ot-shape-complex-use.cc
+2
-1
src/hb-ot-shape-complex-vowel-constraints.hh
src/hb-ot-shape-complex-vowel-constraints.hh
+434
-0
test/shaping/README.md
test/shaping/README.md
+2
-2
test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf
...-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf
+0
-0
test/shaping/data/in-house/tests/use-vowel-letter-spoofing.tests
...aping/data/in-house/tests/use-vowel-letter-spoofing.tests
+94
-0
未找到文件。
src/Makefile.am
浏览文件 @
205737ac
...
...
@@ -295,6 +295,7 @@ GENERATORS = \
gen-os2-unicode-ranges.py
\
gen-tag-table.py
\
gen-use-table.py
\
gen-vowel-constraints.py
\
$(NULL)
EXTRA_DIST
+=
$(GENERATORS)
...
...
@@ -316,13 +317,17 @@ use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.tx
$(AM_V_GEN)
$(builddir)
/
$^
>
$(srcdir)
/hb-ot-shape-complex-use-table.cc
\
||
(
$(RM)
$(srcdir)
/hb-ot-shape-complex-use-table.cc
;
false
)
vowel-constraints
:
gen-vowel-constraints.py use Scripts.txt
$(AM_V_GEN)
$(builddir)
/
$^
>
$(srcdir)
/hb-ot-shape-complex-vowel-constraints.hh
\
||
(
$(RM)
$(srcdir)
/hb-ot-shape-complex-vowel-constraints.hh
;
false
)
emoji-table
:
gen-emoji-table.py emoji-data.txt
$(AM_V_GEN)
$(builddir)
/
$^
>
$(srcdir)
/hb-unicode-emoji-table.hh
\
||
(
$(RM)
$(srcdir)
/hb-unicode-emoji-table.hh
;
false
)
built-sources
:
$(BUILT_SOURCES)
.PHONY
:
unicode-tables arabic-table indic-table tag-table use-table emoji-table built-sources
.PHONY
:
unicode-tables arabic-table indic-table tag-table use-table
vowel-constraints
emoji-table built-sources
RAGEL_GENERATED
=
\
$(
patsubst
%,
$(srcdir)
/%,
$(HB_BASE_RAGEL_GENERATED_sources)
)
\
...
...
src/Makefile.sources
浏览文件 @
205737ac
...
...
@@ -142,6 +142,7 @@ HB_OT_sources = \
hb-ot-shape-complex-use.cc
\
hb-ot-shape-complex-use.hh
\
hb-ot-shape-complex-use-table.cc
\
hb-ot-shape-complex-vowel-constraints.hh
\
hb-ot-shape-complex.hh
\
hb-ot-shape-normalize.hh
\
hb-ot-shape-normalize.cc
\
...
...
src/gen-vowel-constraints.py
0 → 100755
浏览文件 @
205737ac
#!/usr/bin/python
"""Generator of the function to prohibit certain vowel sequences.
It creates ``preprocess_text_vowel_constraints``, which inserts dotted
circles into sequences prohibited by the USE script development spec.
This function should be used as the ``preprocess_text`` of an
``hb_ot_complex_shaper_t``.
It also creates the helper function ``_output_with_dotted_circle``.
"""
from
__future__
import
absolute_import
,
division
,
print_function
,
unicode_literals
import
collections
try
:
from
HTMLParser
import
HTMLParser
def
write
(
s
):
print
(
s
.
encode
(
'utf-8'
),
end
=
''
)
except
ImportError
:
from
html.parser
import
HTMLParser
def
write
(
s
):
sys
.
stdout
.
flush
()
sys
.
stdout
.
buffer
.
write
(
s
.
encode
(
'utf-8'
))
import
itertools
import
io
import
sys
if
len
(
sys
.
argv
)
!=
3
:
print
(
'usage: ./gen-vowel-constraints.py use Scripts.txt'
,
file
=
sys
.
stderr
)
sys
.
exit
(
1
)
try
:
from
html
import
unescape
def
html_unescape
(
parser
,
entity
):
return
unescape
(
entity
)
except
ImportError
:
def
html_unescape
(
parser
,
entity
):
return
parser
.
unescape
(
entity
)
def
expect
(
condition
,
message
=
None
):
if
not
condition
:
if
message
is
None
:
raise
AssertionError
raise
AssertionError
(
message
)
with
io
.
open
(
sys
.
argv
[
2
],
encoding
=
'utf-8'
)
as
f
:
scripts_header
=
[
f
.
readline
()
for
i
in
range
(
2
)]
scripts
=
{}
script_order
=
{}
for
line
in
f
:
j
=
line
.
find
(
'#'
)
if
j
>=
0
:
line
=
line
[:
j
]
fields
=
[
x
.
strip
()
for
x
in
line
.
split
(
';'
)]
if
len
(
fields
)
==
1
:
continue
uu
=
fields
[
0
].
split
(
'..'
)
start
=
int
(
uu
[
0
],
16
)
if
len
(
uu
)
==
1
:
end
=
start
else
:
end
=
int
(
uu
[
1
],
16
)
script
=
fields
[
1
]
for
u
in
range
(
start
,
end
+
1
):
scripts
[
u
]
=
script
if
script
not
in
script_order
:
script_order
[
script
]
=
start
class
ConstraintSet
(
object
):
"""A set of prohibited code point sequences.
Args:
constraint (List[int]): A prohibited code point sequence.
"""
def
__init__
(
self
,
constraint
):
# Either a list or a dictionary. As a list of code points, it
# represents a prohibited code point sequence. As a dictionary,
# it represents a set of prohibited sequences, where each item
# represents the set of prohibited sequences starting with the
# key (a code point) concatenated with any of the values
# (ConstraintSets).
self
.
_c
=
constraint
def
add
(
self
,
constraint
):
"""Add a constraint to this set."""
if
not
constraint
:
return
first
=
constraint
[
0
]
rest
=
constraint
[
1
:]
if
isinstance
(
self
.
_c
,
list
):
if
constraint
==
self
.
_c
[:
len
(
constraint
)]:
self
.
_c
=
constraint
elif
self
.
_c
!=
constraint
[:
len
(
self
.
_c
)]:
self
.
_c
=
{
self
.
_c
[
0
]:
ConstraintSet
(
self
.
_c
[
1
:])}
if
isinstance
(
self
.
_c
,
dict
):
if
first
in
self
.
_c
:
self
.
_c
[
first
].
add
(
rest
)
else
:
self
.
_c
[
first
]
=
ConstraintSet
(
rest
)
def
_indent
(
self
,
depth
):
return
(
' '
*
depth
).
replace
(
' '
,
'
\t
'
)
def
__str__
(
self
,
index
=
0
,
depth
=
4
):
s
=
[]
indent
=
self
.
_indent
(
depth
)
if
isinstance
(
self
.
_c
,
list
):
if
len
(
self
.
_c
)
==
0
:
s
.
append
(
'{}matched = true;
\n
'
.
format
(
indent
))
elif
len
(
self
.
_c
)
==
1
:
s
.
append
(
'{}matched = 0x{:04X}u == buffer->cur ({}).codepoint;
\n
'
.
format
(
indent
,
next
(
iter
(
self
.
_c
)),
index
or
''
))
else
:
s
.
append
(
'{}if (0x{:04X}u == buffer->cur ({}).codepoint &&
\n
'
.
format
(
indent
,
self
.
_c
[
0
],
index
))
s
.
append
(
'{}buffer->idx + {} < count &&
\n
'
.
format
(
self
.
_indent
(
depth
+
2
),
len
(
self
.
_c
)))
for
i
,
cp
in
enumerate
(
self
.
_c
[
1
:],
start
=
1
):
s
.
append
(
'{}0x{:04X}u == buffer->cur ({}).codepoint{}
\n
'
.
format
(
self
.
_indent
(
depth
+
2
),
cp
,
index
+
i
,
')'
if
i
==
len
(
self
.
_c
)
-
1
else
' &&'
))
s
.
append
(
'{}{{
\n
'
.
format
(
indent
))
for
i
in
range
(
len
(
self
.
_c
)):
s
.
append
(
'{}buffer->next_glyph ();
\n
'
.
format
(
self
.
_indent
(
depth
+
1
)))
s
.
append
(
'{}buffer->output_glyph (0x25CCu);
\n
'
.
format
(
self
.
_indent
(
depth
+
1
)))
s
.
append
(
'{}}}
\n
'
.
format
(
indent
))
else
:
s
.
append
(
'{}switch (buffer->cur ({}).codepoint)
\n
'
.
format
(
indent
,
index
or
''
))
s
.
append
(
'{}{{
\n
'
.
format
(
indent
))
cases
=
collections
.
defaultdict
(
set
)
for
first
,
rest
in
sorted
(
self
.
_c
.
items
()):
cases
[
rest
.
__str__
(
index
+
1
,
depth
+
2
)].
add
(
first
)
for
body
,
labels
in
sorted
(
cases
.
items
(),
key
=
lambda
b_ls
:
sorted
(
b_ls
[
1
])[
0
]):
for
i
,
cp
in
enumerate
(
sorted
(
labels
)):
if
i
%
4
==
0
:
s
.
append
(
self
.
_indent
(
depth
+
1
))
else
:
s
.
append
(
' '
)
s
.
append
(
'case 0x{:04X}u:{}'
.
format
(
cp
,
'
\n
'
if
i
%
4
==
3
else
''
))
if
len
(
labels
)
%
4
!=
0
:
s
.
append
(
'
\n
'
)
s
.
append
(
body
)
s
.
append
(
'{}break;
\n
'
.
format
(
self
.
_indent
(
depth
+
2
)))
s
.
append
(
'{}}}
\n
'
.
format
(
indent
))
return
''
.
join
(
s
)
class
USESpecParser
(
HTMLParser
):
"""A parser for the USE script development spec.
Attributes:
header (str): The ``updated_at`` timestamp of the spec.
constraints (Mapping[str, ConstraintSet]): A map of script names
to the scripts' prohibited sequences.
"""
def
__init__
(
self
):
HTMLParser
.
__init__
(
self
)
self
.
header
=
''
self
.
constraints
=
{}
# Whether the next <code> contains the vowel constraints.
self
.
_primed
=
False
# Whether the parser is in the <code> element with the constraints.
self
.
_in_constraints
=
False
# The text of the constraints.
self
.
_constraints
=
''
def
handle_starttag
(
self
,
tag
,
attrs
):
if
tag
==
'meta'
:
for
attr
,
value
in
attrs
:
if
attr
==
'name'
and
value
==
'updated_at'
:
self
.
header
=
self
.
get_starttag_text
()
break
elif
tag
==
'a'
:
for
attr
,
value
in
attrs
:
if
attr
==
'id'
and
value
==
'ivdvconstraints'
:
self
.
_primed
=
True
break
elif
self
.
_primed
and
tag
==
'code'
:
self
.
_primed
=
False
self
.
_in_constraints
=
True
def
handle_endtag
(
self
,
tag
):
self
.
_in_constraints
=
False
def
handle_data
(
self
,
data
):
if
self
.
_in_constraints
:
self
.
_constraints
+=
data
def
handle_charref
(
self
,
name
):
self
.
handle_data
(
html_unescape
(
self
,
'&#%s;'
%
name
))
def
handle_entityref
(
self
,
name
):
self
.
handle_data
(
html_unescape
(
self
,
'&%s;'
%
name
))
def
parse
(
self
,
filename
):
"""Parse the USE script development spec.
Args:
filename (str): The file name of the spec.
"""
with
io
.
open
(
filename
,
encoding
=
'utf-8'
)
as
f
:
self
.
feed
(
f
.
read
())
expect
(
self
.
header
,
'No header found'
)
for
line
in
self
.
_constraints
.
splitlines
():
constraint
=
[
int
(
cp
,
16
)
for
cp
in
line
.
split
(
';'
)[
0
].
strip
().
split
(
' '
)]
expect
(
2
<=
len
(
constraint
),
'Prohibited sequence is too short: {}'
.
format
(
constraint
))
script
=
scripts
[
constraint
[
0
]]
if
script
in
self
.
constraints
:
self
.
constraints
[
script
].
add
(
constraint
)
else
:
self
.
constraints
[
script
]
=
ConstraintSet
(
constraint
)
expect
(
self
.
constraints
,
'No constraints found'
)
use_parser
=
USESpecParser
()
use_parser
.
parse
(
sys
.
argv
[
1
])
print
(
'/* == Start of generated functions == */'
)
print
(
'/*'
)
print
(
' * The following functions are generated by running:'
)
print
(
' *'
)
print
(
' * %s use Scripts.txt'
%
sys
.
argv
[
0
])
print
(
' *'
)
print
(
' * on files with these headers:'
)
print
(
' *'
)
print
(
' * %s'
%
use_parser
.
header
.
strip
())
for
line
in
scripts_header
:
print
(
' * %s'
%
line
.
strip
())
print
(
' */'
)
print
()
print
(
'#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH'
)
print
(
'#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH'
)
print
()
print
(
'static void'
)
print
(
'_output_with_dotted_circle (hb_buffer_t *buffer)'
)
print
(
'{'
)
print
(
' hb_glyph_info_t &dottedcircle = buffer->output_glyph (0x25CCu);'
)
print
(
' _hb_glyph_info_reset_continuation (&dottedcircle);'
)
print
()
print
(
' buffer->next_glyph ();'
)
print
(
'}'
)
print
()
print
(
'static void'
)
print
(
'preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,'
)
print
(
'
\t\t\t\t
hb_buffer_t *buffer,'
)
print
(
'
\t\t\t\t
hb_font_t *font)'
)
print
(
'{'
)
print
(
' /* UGLY UGLY UGLY business of adding dotted-circle in the middle of'
)
print
(
' * vowel-sequences that look like another vowel. Data for each script'
)
print
(
' * collected from the USE script development spec.'
)
print
(
' *'
)
print
(
' * https://github.com/harfbuzz/harfbuzz/issues/1019'
)
print
(
' */'
)
print
(
' bool processed = false;'
)
print
(
' buffer->clear_output ();'
)
print
(
' unsigned int count = buffer->len;'
)
print
(
' switch ((unsigned) buffer->props.script)'
)
print
(
' {'
)
for
script
,
constraints
in
sorted
(
use_parser
.
constraints
.
items
(),
key
=
lambda
s_c
:
script_order
[
s_c
[
0
]]):
print
(
' case HB_SCRIPT_{}:'
.
format
(
script
.
upper
()))
print
(
' for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)'
)
print
(
' {'
)
print
(
'
\t
bool matched = false;'
)
write
(
str
(
constraints
))
print
(
'
\t
buffer->next_glyph ();'
)
print
(
'
\t
if (matched) _output_with_dotted_circle (buffer);'
)
print
(
' }'
)
print
(
' processed = true;'
)
print
(
' break;'
)
print
()
print
(
' default:'
)
print
(
' break;'
)
print
(
' }'
)
print
(
' if (processed)'
)
print
(
' {'
)
print
(
' if (buffer->idx < count)'
)
print
(
' buffer->next_glyph ();'
)
print
(
' if (likely (buffer->successful))'
)
print
(
' buffer->swap_buffers ();'
)
print
(
' }'
)
print
(
'}'
)
print
()
print
(
'#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */'
)
print
()
print
(
'/* == End of generated functions == */'
)
src/hb-ot-shape-complex-indic.cc
浏览文件 @
205737ac
...
...
@@ -25,6 +25,7 @@
*/
#include "hb-ot-shape-complex-indic.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
#include "hb-ot-layout.hh"
...
...
@@ -331,275 +332,6 @@ data_destroy_indic (void *data)
free
(
data
);
}
static
void
_output_with_dotted_circle
(
hb_buffer_t
*
buffer
)
{
hb_glyph_info_t
&
dottedcircle
=
buffer
->
output_glyph
(
0x25CCu
);
_hb_glyph_info_reset_continuation
(
&
dottedcircle
);
buffer
->
next_glyph
();
}
static
void
preprocess_text_indic
(
const
hb_ot_shape_plan_t
*
plan
,
hb_buffer_t
*
buffer
,
hb_font_t
*
font
)
{
/* UGLY UGLY UGLY business of adding dotted-circle in the middle of
* vowel-sequences that look like another vowel. Data for each script
* collected from Unicode 11 book, tables named "Vowel Letters" with
* "Use" and "Do Not Use" columns.
*
* https://github.com/harfbuzz/harfbuzz/issues/1019
*/
bool
processed
=
false
;
buffer
->
clear_output
();
unsigned
int
count
=
buffer
->
len
;
switch
((
unsigned
)
buffer
->
props
.
script
)
{
case
HB_SCRIPT_DEVANAGARI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0905u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x093Au
:
case
0x093Bu
:
case
0x093Eu
:
case
0x0945u
:
case
0x0946u
:
case
0x0949u
:
case
0x094Au
:
case
0x094Bu
:
case
0x094Cu
:
case
0x094Fu
:
case
0x0956u
:
case
0x0957u
:
matched
=
true
;
break
;
}
break
;
case
0x0906u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x093Au
:
case
0x0945u
:
case
0x0946u
:
case
0x0947u
:
case
0x0948u
:
matched
=
true
;
break
;
}
break
;
case
0x0909u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0941u
:
matched
=
true
;
break
;
}
break
;
case
0x090Fu
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0945u
:
case
0x0946u
:
case
0x0947u
:
matched
=
true
;
break
;
}
break
;
case
0x0930u
:
if
(
0x094Du
==
buffer
->
cur
(
1
).
codepoint
&&
buffer
->
idx
+
2
<
count
&&
0x0907u
==
buffer
->
cur
(
2
).
codepoint
)
{
buffer
->
next_glyph
();
buffer
->
next_glyph
();
buffer
->
output_glyph
(
0x25CCu
);
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_BENGALI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0985u
:
matched
=
0x09BE
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x098Bu
:
matched
=
0x09C3
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x098Cu
:
matched
=
0x09E2
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_GURMUKHI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0A05u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0A3Eu
:
case
0x0A48u
:
case
0x0A4Cu
:
matched
=
true
;
break
;
}
break
;
case
0x0A72u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0A3Fu
:
case
0x0A40u
:
case
0x0A47u
:
matched
=
true
;
break
;
}
break
;
case
0x0A73u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0A41u
:
case
0x0A42u
:
case
0x0A4Bu
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_GUJARATI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0A85u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0ABEu
:
case
0x0AC5u
:
case
0x0AC7u
:
case
0x0AC8u
:
case
0x0AC9u
:
case
0x0ACBu
:
case
0x0ACCu
:
matched
=
true
;
break
;
}
break
;
case
0x0AC5u
:
matched
=
0x0ABE
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_ORIYA
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0B05u
:
matched
=
0x0B3E
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0B0Fu
:
case
0x0B13u
:
matched
=
0x0B57
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_TELUGU
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0C12u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0C4Cu
:
case
0x0C55u
:
matched
=
true
;
break
;
}
break
;
case
0x0C3Fu
:
case
0x0C46u
:
case
0xC4Au
:
matched
=
0x0C55
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_KANNADA
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0C89u
:
case
0x0C8Bu
:
matched
=
0x0CBE
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0C92u
:
matched
=
0x0CCC
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_MALAYALAM
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0D07u
:
case
0x0D09u
:
matched
=
0x0D57
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0D0Eu
:
matched
=
0x0D46
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0D12u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0D3Eu
:
case
0x0D57u
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
default:
break
;
}
if
(
processed
)
{
if
(
buffer
->
idx
<
count
)
buffer
->
next_glyph
();
if
(
likely
(
buffer
->
successful
))
buffer
->
swap_buffers
();
}
}
static
indic_position_t
consonant_position_from_face
(
const
indic_shape_plan_t
*
indic_plan
,
const
hb_codepoint_t
consonant
,
...
...
@@ -1884,7 +1616,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
override_features_indic
,
data_create_indic
,
data_destroy_indic
,
preprocess_text_
indic
,
preprocess_text_
vowel_constraints
,
nullptr
,
/* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT
,
decompose_indic
,
...
...
src/hb-ot-shape-complex-use.cc
浏览文件 @
205737ac
...
...
@@ -28,6 +28,7 @@
#include "hb-ot-shape-complex-use.hh"
#include "hb-ot-shape-complex-arabic.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
/* buffer var allocations */
#define use_category() complex_var_u8_0()
...
...
@@ -591,7 +592,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
nullptr
,
/* override_features */
data_create_use
,
data_destroy_use
,
nullptr
,
/* preprocess_text */
preprocess_text_vowel_constraints
,
nullptr
,
/* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT
,
nullptr
,
/* decompose */
...
...
src/hb-ot-shape-complex-vowel-constraints.hh
0 → 100644
浏览文件 @
205737ac
/* == Start of generated functions == */
/*
* The following functions are generated by running:
*
* ./gen-vowel-constraints.py use Scripts.txt
*
* on files with these headers:
*
* <meta name="updated_at" content="2018-03-27 12:21 AM" />
* # Scripts-11.0.0.txt
* # Date: 2018-02-21, 05:34:31 GMT
*/
#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
static
void
_output_with_dotted_circle
(
hb_buffer_t
*
buffer
)
{
hb_glyph_info_t
&
dottedcircle
=
buffer
->
output_glyph
(
0x25CCu
);
_hb_glyph_info_reset_continuation
(
&
dottedcircle
);
buffer
->
next_glyph
();
}
static
void
preprocess_text_vowel_constraints
(
const
hb_ot_shape_plan_t
*
plan
,
hb_buffer_t
*
buffer
,
hb_font_t
*
font
)
{
/* UGLY UGLY UGLY business of adding dotted-circle in the middle of
* vowel-sequences that look like another vowel. Data for each script
* collected from the USE script development spec.
*
* https://github.com/harfbuzz/harfbuzz/issues/1019
*/
bool
processed
=
false
;
buffer
->
clear_output
();
unsigned
int
count
=
buffer
->
len
;
switch
((
unsigned
)
buffer
->
props
.
script
)
{
case
HB_SCRIPT_DEVANAGARI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0905u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x093Au
:
case
0x093Bu
:
case
0x093Eu
:
case
0x0945u
:
case
0x0946u
:
case
0x0949u
:
case
0x094Au
:
case
0x094Bu
:
case
0x094Cu
:
case
0x094Fu
:
case
0x0956u
:
case
0x0957u
:
matched
=
true
;
break
;
}
break
;
case
0x0906u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x093Au
:
case
0x0945u
:
case
0x0946u
:
case
0x0947u
:
case
0x0948u
:
matched
=
true
;
break
;
}
break
;
case
0x0909u
:
matched
=
0x0941u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x090Fu
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0945u
:
case
0x0946u
:
case
0x0947u
:
matched
=
true
;
break
;
}
break
;
case
0x0930u
:
if
(
0x094Du
==
buffer
->
cur
(
1
).
codepoint
&&
buffer
->
idx
+
2
<
count
&&
0x0907u
==
buffer
->
cur
(
2
).
codepoint
)
{
buffer
->
next_glyph
();
buffer
->
next_glyph
();
buffer
->
output_glyph
(
0x25CCu
);
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_BENGALI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0985u
:
matched
=
0x09BEu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x098Bu
:
matched
=
0x09C3u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x098Cu
:
matched
=
0x09E2u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_GURMUKHI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0A05u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0A3Eu
:
case
0x0A48u
:
case
0x0A4Cu
:
matched
=
true
;
break
;
}
break
;
case
0x0A72u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0A3Fu
:
case
0x0A40u
:
case
0x0A47u
:
matched
=
true
;
break
;
}
break
;
case
0x0A73u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0A41u
:
case
0x0A42u
:
case
0x0A4Bu
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_GUJARATI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0A85u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0ABEu
:
case
0x0AC5u
:
case
0x0AC7u
:
case
0x0AC8u
:
case
0x0AC9u
:
case
0x0ACBu
:
case
0x0ACCu
:
matched
=
true
;
break
;
}
break
;
case
0x0AC5u
:
matched
=
0x0ABEu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_ORIYA
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0B05u
:
matched
=
0x0B3Eu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0B0Fu
:
case
0x0B13u
:
matched
=
0x0B57u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_TELUGU
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0C12u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0C4Cu
:
case
0x0C55u
:
matched
=
true
;
break
;
}
break
;
case
0x0C3Fu
:
case
0x0C46u
:
case
0x0C4Au
:
matched
=
0x0C55u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_KANNADA
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0C89u
:
case
0x0C8Bu
:
matched
=
0x0CBEu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0C92u
:
matched
=
0x0CCCu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_MALAYALAM
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0D07u
:
case
0x0D09u
:
matched
=
0x0D57u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0D0Eu
:
matched
=
0x0D46u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0D12u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0D3Eu
:
case
0x0D57u
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_SINHALA
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x0D85u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0DCFu
:
case
0x0DD0u
:
case
0x0DD1u
:
matched
=
true
;
break
;
}
break
;
case
0x0D8Bu
:
case
0x0D8Fu
:
case
0x0D94u
:
matched
=
0x0DDFu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0D8Du
:
matched
=
0x0DD8u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x0D91u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x0DCAu
:
case
0x0DD9u
:
case
0x0DDAu
:
case
0x0DDCu
:
case
0x0DDDu
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_BRAHMI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x11005u
:
matched
=
0x11038u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x1100Bu
:
matched
=
0x1103Eu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x1100Fu
:
matched
=
0x11042u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_KHUDAWADI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x112B0u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x112E0u
:
case
0x112E5u
:
case
0x112E6u
:
case
0x112E7u
:
case
0x112E8u
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_TIRHUTA
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x11481u
:
matched
=
0x114B0u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x1148Bu
:
case
0x1148Du
:
matched
=
0x114BAu
==
buffer
->
cur
(
1
).
codepoint
;
break
;
case
0x114AAu
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x114B5u
:
case
0x114B6u
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_MODI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x11600u
:
case
0x11601u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x11639u
:
case
0x1163Au
:
matched
=
true
;
break
;
}
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
case
HB_SCRIPT_TAKRI
:
for
(
buffer
->
idx
=
0
;
buffer
->
idx
+
1
<
count
&&
buffer
->
successful
;)
{
bool
matched
=
false
;
switch
(
buffer
->
cur
().
codepoint
)
{
case
0x11680u
:
switch
(
buffer
->
cur
(
1
).
codepoint
)
{
case
0x116ADu
:
case
0x116B4u
:
case
0x116B5u
:
matched
=
true
;
break
;
}
break
;
case
0x11686u
:
matched
=
0x116B2u
==
buffer
->
cur
(
1
).
codepoint
;
break
;
}
buffer
->
next_glyph
();
if
(
matched
)
_output_with_dotted_circle
(
buffer
);
}
processed
=
true
;
break
;
default:
break
;
}
if
(
processed
)
{
if
(
buffer
->
idx
<
count
)
buffer
->
next_glyph
();
if
(
likely
(
buffer
->
successful
))
buffer
->
swap_buffers
();
}
}
#endif
/* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
/* == End of generated functions == */
test/shaping/README.md
浏览文件 @
205737ac
...
...
@@ -25,10 +25,10 @@ what this does is:
*
If the outputs differ, recording fails. Otherwise, it will move the
subset font file into
`data/in-house/fonts`
and name it after its
hash, and print out the test case input, which you can then redirect
to an existing or new test file in
`data/in-house/tests`
using
`-o
=
`
,
to an existing or new test file in
`data/in-house/tests`
using
`-o`
,
e.g.:
```
sh
$
./hb-unicode-encode 41 42 43 627 | ./record-test.sh
-o
=
data/in-house/tests/test-name.test ../../util/hb-shape font.ttf
$
./hb-unicode-encode 41 42 43 627 | ./record-test.sh
-o
data/in-house/tests/test-name.test ../../util/hb-shape font.ttf
```
If you created a new test file, add it to
`data/in-house/Makefile.sources`
...
...
test/shaping/data/in-house/fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf
0 → 100644
浏览文件 @
205737ac
文件已添加
test/shaping/data/in-house/tests/use-vowel-letter-spoofing.tests
0 → 100644
浏览文件 @
205737ac
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+093A:[uni0905=0+500|uni25CC=0+500|uni093A=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+093B:[uni0905=0+500|uni25CC=0+500|uni093B=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+093E:[uni0905=0+500|uni25CC=0+500|uni093E=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0945:[uni0905=0+500|uni25CC=0+500|uni0945=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0946:[uni0905=0+500|uni25CC=0+500|uni0946=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0949:[uni0905=0+500|uni25CC=0+500|uni0949=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094A:[uni0905=0+500|uni25CC=0+500|uni094A=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094B:[uni0905=0+500|uni25CC=0+500|uni094B=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094C:[uni0905=0+500|uni25CC=0+500|uni094C=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+094F:[uni0905=0+500|uni25CC=0+500|uni094F=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0956:[uni0905=0+500|uni25CC=0+500|uni0956=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0905,U+0957:[uni0905=0+500|uni25CC=0+500|uni0957=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+093A:[uni0906=0+500|uni25CC=0+500|uni093A=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0945:[uni0906=0+500|uni25CC=0+500|uni0945=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0946:[uni0906=0+500|uni25CC=0+500|uni0946=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0947:[uni0906=0+500|uni25CC=0+500|uni0947=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0906,U+0948:[uni0906=0+500|uni25CC=0+500|uni0948=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0909,U+0941:[uni0909=0+500|uni25CC=0+500|uni0941=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+090F,U+0945:[uni090F=0+500|uni25CC=0+500|uni0945=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+090F,U+0946:[uni090F=0+500|uni25CC=0+500|uni0946=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+090F,U+0947:[uni090F=0+500|uni25CC=0+500|uni0947=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0930,U+094D,U+0907:[uni0930=0+500|uni094D=0+500|uni25CC=2+500|uni0907=2+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0985,U+09BE:[uni0985=0+500|uni25CC=0+500|.notdef=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+098B,U+09C3:[uni098B=0+500|uni25CC=0+500|uni09C3=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+098C,U+09E2:[uni098C=0+500|uni25CC=0+500|uni09E2=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A05,U+0A3E:[uni0A05=0+500|uni25CC=0+500|uni0A3E=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A05,U+0A48:[uni0A05=0+500|uni25CC=0+500|uni0A48=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A05,U+0A4C:[uni0A05=0+500|uni25CC=0+500|uni0A4C=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A72,U+0A3F:[uni0A72=0+500|uni0A3F=0+500|uni25CC=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A72,U+0A40:[uni0A72=0+500|uni25CC=0+500|uni0A40=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A72,U+0A47:[uni0A72=0+500|uni25CC=0+500|uni0A47=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A73,U+0A41:[uni0A73=0+500|uni25CC=0+500|uni0A41=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A73,U+0A42:[uni0A73=0+500|uni25CC=0+500|uni0A42=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A73,U+0A4B:[uni0A73=0+500|uni25CC=0+500|uni0A4B=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ABE,U+0AC5:[uni0A85=0+500|uni25CC=0+500|uni0ABE=0+500|uni25CC=0+500|uni0AC5=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ABE,U+0AC8:[uni0A85=0+500|uni25CC=0+500|uni0ABE=0+500|uni25CC=0+500|uni0AC8=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ABE:[uni0A85=0+500|uni25CC=0+500|uni0ABE=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC5:[uni0A85=0+500|uni25CC=0+500|uni0AC5=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC7:[uni0A85=0+500|uni25CC=0+500|uni0AC7=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC8:[uni0A85=0+500|uni25CC=0+500|uni0AC8=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0AC9:[uni0A85=0+500|uni25CC=0+500|uni0AC9=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ACB:[uni0A85=0+500|uni25CC=0+500|uni0ACB=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0A85,U+0ACC:[uni0A85=0+500|uni25CC=0+500|uni0ACC=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0AC5,U+0ABE:[uni25CC=0+500|uni0AC5=0+500|uni25CC=0+500|uni0ABE=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0B05,U+0B3E:[uni0B05=0+500|uni25CC=0+500|uni0B3E=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0B0F,U+0B57:[uni0B0F=0+500|uni25CC=0+500|uni0B57=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0B13,U+0B57:[uni0B13=0+500|uni25CC=0+500|uni0B57=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C12,U+0C4C:[uni0C12=0+500|uni25CC=0+500|uni0C4C=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C12,U+0C55:[uni0C12=0+500|uni25CC=0+500|uni0C55=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C3F,U+0C55:[uni25CC=0+500|uni0C3F=0+500|uni25CC=0+500|uni0C55=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C46,U+0C55:[uni25CC=0+500|uni0C46=0+500|uni25CC=0+500|uni0C55=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C4A,U+0C55:[uni25CC=0+500|uni0C4A=0+500|uni25CC=0+500|uni0C55=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C89,U+0CBE:[uni0C89=0+500|uni25CC=0+500|uni0CBE=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C8B,U+0CBE:[uni0C8B=0+500|uni25CC=0+500|uni0CBE=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0C92,U+0CCC:[uni0C92=0+500|uni25CC=0+500|uni0CCC=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D07,U+0D57:[uni0D07=0+500|uni25CC=0+500|uni0D57=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D09,U+0D57:[uni0D09=0+500|uni25CC=0+500|uni0D57=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D0E,U+0D46:[uni0D0E=0+500|uni0D46=0+500|uni25CC=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D12,U+0D3E:[uni0D12=0+500|uni25CC=0+500|uni0D3E=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D12,U+0D57:[uni0D12=0+500|uni25CC=0+500|uni0D57=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D85,U+0DCF:[uni0D85=0+500|uni25CC=0+500|uni0DCF=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D85,U+0DD0:[uni0D85=0+500|uni25CC=0+500|uni0DD0=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D85,U+0DD1:[uni0D85=0+500|uni25CC=0+500|uni0DD1=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D8B,U+0DDF:[uni0D8B=0+500|uni25CC=0+500|uni0DDF=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D8D,U+0DD8:[uni0D8D=0+500|uni25CC=0+500|uni0DD8=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D8F,U+0DDF:[uni0D8F=0+500|uni25CC=0+500|uni0DDF=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DCA:[uni0D91=0+500|uni25CC=0+500|uni0DCA=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DD9:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDA:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCA=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDC:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCF=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDD:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCF=0+500|uni0DCA=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D91,U+0DDD:[uni0D91=0+500|uni0DD9=0+500|uni25CC=0+500|uni0DCF=0+500|uni0DCA=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+0D94,U+0DDF:[uni0D94=0+500|uni25CC=0+500|uni0DDF=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11005,U+11038:[u11005=0+500|uni25CC=0+500|u11038=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1100B,U+1103E:[u1100B=0+500|uni25CC=0+500|u1103E=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1100F,U+11042:[u1100F=0+500|uni25CC=0+500|u11042=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E0:[u112B0=0+500|uni25CC=0+500|u112E0=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E5:[u112B0=0+500|uni25CC=0+500|u112E5=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E6:[u112B0=0+500|uni25CC=0+500|u112E6=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E7:[u112B0=0+500|uni25CC=0+500|u112E7=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+112B0,U+112E8:[u112B0=0+500|uni25CC=0+500|u112E8=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11481,U+114B0:[u11481=0+500|uni25CC=0+500|u114B0=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1148B,U+114BA:[u1148B=0+500|uni25CC=0+500|u114BA=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+1148D,U+114BA:[u1148D=0+500|uni25CC=0+500|u114BA=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+114AA,U+114B5:[u114AA=0+500|uni25CC=0+500|u114B5=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+114AA,U+114B6:[u114AA=0+500|uni25CC=0+500|u114B6=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11600,U+11639:[u11600=0+500|uni25CC=0+500|u11639=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11600,U+1163A:[u11600=0+500|uni25CC=0+500|u1163A=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11601,U+11639:[u11601=0+500|uni25CC=0+500|u11639=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11601,U+1163A:[u11601=0+500|uni25CC=0+500|u1163A=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11680,U+116AD:[u11680=0+500|uni25CC=0+500|u116AD=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11680,U+116B4:[u11680=0+500|uni25CC=0+500|u116B4=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11680,U+116B5:[u11680=0+500|uni25CC=0+500|u116B5=0+500]
../fonts/46669c8860cbfea13562a6ca0d83130ee571137b.ttf::U+11686,U+116B2:[u11686=0+500|uni25CC=0+500|u116B2=0+500]
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录