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 = \
...
@@ -295,6 +295,7 @@ GENERATORS = \
gen-os2-unicode-ranges.py
\
gen-os2-unicode-ranges.py
\
gen-tag-table.py
\
gen-tag-table.py
\
gen-use-table.py
\
gen-use-table.py
\
gen-vowel-constraints.py
\
$(NULL)
$(NULL)
EXTRA_DIST
+=
$(GENERATORS)
EXTRA_DIST
+=
$(GENERATORS)
...
@@ -316,13 +317,17 @@ use-table: gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.tx
...
@@ -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
\
$(AM_V_GEN)
$(builddir)
/
$^
>
$(srcdir)
/hb-ot-shape-complex-use-table.cc
\
||
(
$(RM)
$(srcdir)
/hb-ot-shape-complex-use-table.cc
;
false
)
||
(
$(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
emoji-table
:
gen-emoji-table.py emoji-data.txt
$(AM_V_GEN)
$(builddir)
/
$^
>
$(srcdir)
/hb-unicode-emoji-table.hh
\
$(AM_V_GEN)
$(builddir)
/
$^
>
$(srcdir)
/hb-unicode-emoji-table.hh
\
||
(
$(RM)
$(srcdir)
/hb-unicode-emoji-table.hh
;
false
)
||
(
$(RM)
$(srcdir)
/hb-unicode-emoji-table.hh
;
false
)
built-sources
:
$(BUILT_SOURCES)
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
=
\
RAGEL_GENERATED
=
\
$(
patsubst
%,
$(srcdir)
/%,
$(HB_BASE_RAGEL_GENERATED_sources)
)
\
$(
patsubst
%,
$(srcdir)
/%,
$(HB_BASE_RAGEL_GENERATED_sources)
)
\
...
...
src/Makefile.sources
浏览文件 @
205737ac
...
@@ -142,6 +142,7 @@ HB_OT_sources = \
...
@@ -142,6 +142,7 @@ HB_OT_sources = \
hb-ot-shape-complex-use.cc
\
hb-ot-shape-complex-use.cc
\
hb-ot-shape-complex-use.hh
\
hb-ot-shape-complex-use.hh
\
hb-ot-shape-complex-use-table.cc
\
hb-ot-shape-complex-use-table.cc
\
hb-ot-shape-complex-vowel-constraints.hh
\
hb-ot-shape-complex.hh
\
hb-ot-shape-complex.hh
\
hb-ot-shape-normalize.hh
\
hb-ot-shape-normalize.hh
\
hb-ot-shape-normalize.cc
\
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 @@
...
@@ -25,6 +25,7 @@
*/
*/
#include "hb-ot-shape-complex-indic.hh"
#include "hb-ot-shape-complex-indic.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
#include "hb-ot-layout.hh"
#include "hb-ot-layout.hh"
...
@@ -331,275 +332,6 @@ data_destroy_indic (void *data)
...
@@ -331,275 +332,6 @@ data_destroy_indic (void *data)
free
(
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
static
indic_position_t
consonant_position_from_face
(
const
indic_shape_plan_t
*
indic_plan
,
consonant_position_from_face
(
const
indic_shape_plan_t
*
indic_plan
,
const
hb_codepoint_t
consonant
,
const
hb_codepoint_t
consonant
,
...
@@ -1884,7 +1616,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
...
@@ -1884,7 +1616,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
override_features_indic
,
override_features_indic
,
data_create_indic
,
data_create_indic
,
data_destroy_indic
,
data_destroy_indic
,
preprocess_text_
indic
,
preprocess_text_
vowel_constraints
,
nullptr
,
/* postprocess_glyphs */
nullptr
,
/* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT
,
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT
,
decompose_indic
,
decompose_indic
,
...
...
src/hb-ot-shape-complex-use.cc
浏览文件 @
205737ac
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include "hb-ot-shape-complex-use.hh"
#include "hb-ot-shape-complex-use.hh"
#include "hb-ot-shape-complex-arabic.hh"
#include "hb-ot-shape-complex-arabic.hh"
#include "hb-ot-shape-complex-vowel-constraints.hh"
/* buffer var allocations */
/* buffer var allocations */
#define use_category() complex_var_u8_0()
#define use_category() complex_var_u8_0()
...
@@ -591,7 +592,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
...
@@ -591,7 +592,7 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
nullptr
,
/* override_features */
nullptr
,
/* override_features */
data_create_use
,
data_create_use
,
data_destroy_use
,
data_destroy_use
,
nullptr
,
/* preprocess_text */
preprocess_text_vowel_constraints
,
nullptr
,
/* postprocess_glyphs */
nullptr
,
/* postprocess_glyphs */
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT
,
HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT
,
nullptr
,
/* decompose */
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:
...
@@ -25,10 +25,10 @@ what this does is:
*
If the outputs differ, recording fails. Otherwise, it will move the
*
If the outputs differ, recording fails. Otherwise, it will move the
subset font file into
`data/in-house/fonts`
and name it after its
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
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.:
e.g.:
```
sh
```
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`
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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录