Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Harfbuzz
提交
02d864aa
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看板
提交
02d864aa
编写于
4月 15, 2019
作者:
B
Behdad Esfahbod
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add HB_FUNCOBJ()
Fixes
https://github.com/harfbuzz/harfbuzz/issues/1651
上级
60be1450
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
63 addition
and
50 deletion
+63
-50
src/hb-algs.hh
src/hb-algs.hh
+15
-13
src/hb-iter.hh
src/hb-iter.hh
+28
-28
src/hb-meta.hh
src/hb-meta.hh
+13
-9
src/hb.hh
src/hb.hh
+7
-0
未找到文件。
src/hb-algs.hh
浏览文件 @
02d864aa
/*
/*
* Copyright © 2017 Google, Inc.
* Copyright © 2017 Google, Inc.
* Copyright © 2019 Google, Inc.
*
*
* This is part of HarfBuzz, a text shaping library.
* This is part of HarfBuzz, a text shaping library.
*
*
...
@@ -22,6 +23,7 @@
...
@@ -22,6 +23,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*
* Google Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod
* Facebook Author(s): Behdad Esfahbod
*/
*/
#ifndef HB_ALGS_HH
#ifndef HB_ALGS_HH
...
@@ -54,19 +56,19 @@ struct
...
@@ -54,19 +56,19 @@ struct
/* Knuth's multiplicative method: */
/* Knuth's multiplicative method: */
return
(
uint32_t
)
v
*
2654435761u
;
return
(
uint32_t
)
v
*
2654435761u
;
}
}
}
static
const
hb_hash
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_hash
)
;
st
atic
const
st
ruct
struct
{
{
template
<
typename
T
>
T
template
<
typename
T
>
T
operator
()
(
const
T
&
v
)
const
{
return
v
;
}
operator
()
(
const
T
&
v
)
const
{
return
v
;
}
}
hb_identity
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_identity
)
;
st
atic
const
st
ruct
struct
{
{
template
<
typename
T
>
bool
template
<
typename
T
>
bool
operator
()
(
const
T
&
v
)
const
{
return
bool
(
v
);
}
operator
()
(
const
T
&
v
)
const
{
return
bool
(
v
);
}
}
hb_bool
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_bool
)
;
template
<
typename
T1
,
typename
T2
>
template
<
typename
T1
,
typename
T2
>
struct
hb_pair_t
struct
hb_pair_t
...
@@ -86,28 +88,28 @@ struct hb_pair_t
...
@@ -86,28 +88,28 @@ struct hb_pair_t
template
<
typename
T1
,
typename
T2
>
static
inline
hb_pair_t
<
T1
,
T2
>
template
<
typename
T1
,
typename
T2
>
static
inline
hb_pair_t
<
T1
,
T2
>
hb_pair
(
T1
&&
a
,
T2
&&
b
)
{
return
hb_pair_t
<
T1
,
T2
>
(
a
,
b
);
}
hb_pair
(
T1
&&
a
,
T2
&&
b
)
{
return
hb_pair_t
<
T1
,
T2
>
(
a
,
b
);
}
st
atic
const
st
ruct
struct
{
{
template
<
typename
Pair
>
decltype
(
hb_declval
(
Pair
).
first
)
template
<
typename
Pair
>
decltype
(
hb_declval
(
Pair
).
first
)
operator
()
(
const
Pair
&
pair
)
const
{
return
pair
.
first
;
}
operator
()
(
const
Pair
&
pair
)
const
{
return
pair
.
first
;
}
}
hb_first
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_first
)
;
st
atic
const
st
ruct
struct
{
{
template
<
typename
Pair
>
decltype
(
hb_declval
(
Pair
).
second
)
template
<
typename
Pair
>
decltype
(
hb_declval
(
Pair
).
second
)
operator
()
(
const
Pair
&
pair
)
const
{
return
pair
.
second
;
}
operator
()
(
const
Pair
&
pair
)
const
{
return
pair
.
second
;
}
}
hb_second
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_second
)
;
st
atic
const
st
ruct
struct
{
{
template
<
typename
T
,
typename
T2
>
T
template
<
typename
T
,
typename
T2
>
T
operator
()
(
const
T
&
a
,
const
T2
&
b
)
const
{
return
a
<=
b
?
a
:
b
;
}
operator
()
(
const
T
&
a
,
const
T2
&
b
)
const
{
return
a
<=
b
?
a
:
b
;
}
}
hb_min
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_min
)
;
st
atic
const
st
ruct
struct
{
{
template
<
typename
T
,
typename
T2
>
T
template
<
typename
T
,
typename
T2
>
T
operator
()
(
const
T
&
a
,
const
T2
&
b
)
const
{
return
a
>=
b
?
a
:
b
;
}
operator
()
(
const
T
&
a
,
const
T2
&
b
)
const
{
return
a
>=
b
?
a
:
b
;
}
}
hb_max
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_max
)
;
/*
/*
...
...
src/hb-iter.hh
浏览文件 @
02d864aa
/*
/*
* Copyright © 2018 Google, Inc.
* Copyright © 2018 Google, Inc.
* Copyright © 2019 Google, Inc.
*
*
* This is part of HarfBuzz, a text shaping library.
* This is part of HarfBuzz, a text shaping library.
*
*
...
@@ -22,6 +23,7 @@
...
@@ -22,6 +23,7 @@
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*
* Google Author(s): Behdad Esfahbod
* Google Author(s): Behdad Esfahbod
* Facebook Author(s): Behdad Esfahbod
*/
*/
#ifndef HB_ITER_HH
#ifndef HB_ITER_HH
...
@@ -130,7 +132,7 @@ struct hb_iter_t
...
@@ -130,7 +132,7 @@ struct hb_iter_t
template
<
typename
>
struct
hb_array_t
;
template
<
typename
>
struct
hb_array_t
;
st
atic
const
st
ruct
struct
{
{
template
<
typename
T
>
template
<
typename
T
>
hb_iter_t
(
T
)
hb_iter_t
(
T
)
...
@@ -147,7 +149,7 @@ static const struct
...
@@ -147,7 +149,7 @@ static const struct
operator
()
(
Type
(
&
array
)[
length
])
const
operator
()
(
Type
(
&
array
)[
length
])
const
{
return
hb_array_t
<
Type
>
(
array
,
length
);
}
{
return
hb_array_t
<
Type
>
(
array
,
length
);
}
}
hb_iter
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_iter
)
;
/* Mixin to fill in what the subclass doesn't provide. */
/* Mixin to fill in what the subclass doesn't provide. */
...
@@ -298,13 +300,13 @@ struct hb_map_iter_factory_t
...
@@ -298,13 +300,13 @@ struct hb_map_iter_factory_t
private:
private:
Proj
f
;
Proj
f
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Proj
>
template
<
typename
Proj
>
hb_map_iter_factory_t
<
Proj
>
hb_map_iter_factory_t
<
Proj
>
operator
()
(
Proj
&&
f
)
const
operator
()
(
Proj
&&
f
)
const
{
return
hb_map_iter_factory_t
<
Proj
>
(
f
);
}
{
return
hb_map_iter_factory_t
<
Proj
>
(
f
);
}
}
hb_map
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_map
)
;
template
<
typename
Iter
,
typename
Pred
,
typename
Proj
,
template
<
typename
Iter
,
typename
Pred
,
typename
Proj
,
hb_enable_if
(
hb_is_iterator
(
Iter
))>
hb_enable_if
(
hb_is_iterator
(
Iter
))>
...
@@ -342,14 +344,14 @@ struct hb_filter_iter_factory_t
...
@@ -342,14 +344,14 @@ struct hb_filter_iter_factory_t
Pred
p
;
Pred
p
;
Proj
f
;
Proj
f
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Pred
=
decltype
((
hb_bool
)),
template
<
typename
Pred
=
decltype
((
hb_bool
)),
typename
Proj
=
decltype
((
hb_identity
))>
typename
Proj
=
decltype
((
hb_identity
))>
hb_filter_iter_factory_t
<
Pred
,
Proj
>
hb_filter_iter_factory_t
<
Pred
,
Proj
>
operator
()
(
Pred
&&
p
=
hb_bool
,
Proj
&&
f
=
hb_identity
)
const
operator
()
(
Pred
&&
p
=
hb_bool
,
Proj
&&
f
=
hb_identity
)
const
{
return
hb_filter_iter_factory_t
<
Pred
,
Proj
>
(
p
,
f
);
}
{
return
hb_filter_iter_factory_t
<
Pred
,
Proj
>
(
p
,
f
);
}
}
hb_filter
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_filter
)
;
template
<
typename
Redu
,
typename
InitT
>
template
<
typename
Redu
,
typename
InitT
>
struct
hb_reduce_t
struct
hb_reduce_t
...
@@ -372,13 +374,13 @@ struct hb_reduce_t
...
@@ -372,13 +374,13 @@ struct hb_reduce_t
Redu
r
;
Redu
r
;
InitT
init_value
;
InitT
init_value
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Redu
,
typename
InitT
>
template
<
typename
Redu
,
typename
InitT
>
hb_reduce_t
<
Redu
,
InitT
>
hb_reduce_t
<
Redu
,
InitT
>
operator
()
(
Redu
&&
r
,
InitT
init_value
)
const
operator
()
(
Redu
&&
r
,
InitT
init_value
)
const
{
return
hb_reduce_t
<
Redu
,
InitT
>
(
r
,
init_value
);
}
{
return
hb_reduce_t
<
Redu
,
InitT
>
(
r
,
init_value
);
}
}
hb_reduce
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_reduce
)
;
/* hb_zip() */
/* hb_zip() */
...
@@ -411,14 +413,14 @@ struct hb_zip_iter_t :
...
@@ -411,14 +413,14 @@ struct hb_zip_iter_t :
A
a
;
A
a
;
B
b
;
B
b
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
A
,
typename
B
,
template
<
typename
A
,
typename
B
,
hb_enable_if
(
hb_is_iterable
(
A
)
&&
hb_is_iterable
(
B
))>
hb_enable_if
(
hb_is_iterable
(
A
)
&&
hb_is_iterable
(
B
))>
hb_zip_iter_t
<
hb_iter_t
(
A
),
hb_iter_t
(
B
)
>
hb_zip_iter_t
<
hb_iter_t
(
A
),
hb_iter_t
(
B
)
>
operator
()
(
A
&
a
,
B
&
b
)
const
operator
()
(
A
&
a
,
B
&
b
)
const
{
return
hb_zip_iter_t
<
hb_iter_t
(
A
),
hb_iter_t
(
B
)
>
(
hb_iter
(
a
),
hb_iter
(
b
));
}
{
return
hb_zip_iter_t
<
hb_iter_t
(
A
),
hb_iter_t
(
B
)
>
(
hb_iter
(
a
),
hb_iter
(
b
));
}
}
hb_zip
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_zip
)
;
/* hb_enumerate */
/* hb_enumerate */
...
@@ -446,14 +448,14 @@ struct hb_enumerate_iter_t :
...
@@ -446,14 +448,14 @@ struct hb_enumerate_iter_t :
unsigned
i
;
unsigned
i
;
Iter
it
;
Iter
it
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Iterable
,
template
<
typename
Iterable
,
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
hb_enumerate_iter_t
<
hb_iter_t
(
Iterable
)
>
hb_enumerate_iter_t
<
hb_iter_t
(
Iterable
)
>
operator
()
(
Iterable
&
it
)
const
operator
()
(
Iterable
&
it
)
const
{
return
hb_enumerate_iter_t
<
hb_iter_t
(
Iterable
)
>
(
hb_iter
(
it
));
}
{
return
hb_enumerate_iter_t
<
hb_iter_t
(
Iterable
)
>
(
hb_iter
(
it
));
}
}
hb_enumerate
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_enumerate
)
;
/* hb_apply() */
/* hb_apply() */
...
@@ -474,7 +476,7 @@ struct hb_apply_t
...
@@ -474,7 +476,7 @@ struct hb_apply_t
private:
private:
Appl
a
;
Appl
a
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Appl
>
hb_apply_t
<
Appl
>
template
<
typename
Appl
>
hb_apply_t
<
Appl
>
operator
()
(
Appl
&&
a
)
const
operator
()
(
Appl
&&
a
)
const
...
@@ -483,7 +485,7 @@ static const struct
...
@@ -483,7 +485,7 @@ static const struct
template
<
typename
Appl
>
hb_apply_t
<
Appl
&>
template
<
typename
Appl
>
hb_apply_t
<
Appl
&>
operator
()
(
Appl
*
a
)
const
operator
()
(
Appl
*
a
)
const
{
return
hb_apply_t
<
Appl
&>
(
*
a
);
}
{
return
hb_apply_t
<
Appl
&>
(
*
a
);
}
}
hb_apply
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_apply
)
;
/* hb_sink() */
/* hb_sink() */
...
@@ -504,7 +506,7 @@ struct hb_sink_t
...
@@ -504,7 +506,7 @@ struct hb_sink_t
private:
private:
Sink
s
;
Sink
s
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Sink
>
hb_sink_t
<
Sink
>
template
<
typename
Sink
>
hb_sink_t
<
Sink
>
operator
()
(
Sink
&&
s
)
const
operator
()
(
Sink
&&
s
)
const
...
@@ -513,11 +515,11 @@ static const struct
...
@@ -513,11 +515,11 @@ static const struct
template
<
typename
Sink
>
hb_sink_t
<
Sink
&>
template
<
typename
Sink
>
hb_sink_t
<
Sink
&>
operator
()
(
Sink
*
s
)
const
operator
()
(
Sink
*
s
)
const
{
return
hb_sink_t
<
Sink
&>
(
*
s
);
}
{
return
hb_sink_t
<
Sink
&>
(
*
s
);
}
}
hb_sink
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_sink
)
;
/* hb-drain: hb_sink to void / blackhole / /dev/null. */
/* hb-drain: hb_sink to void / blackhole / /dev/null. */
st
atic
const
st
ruct
struct
{
{
template
<
typename
Iter
,
template
<
typename
Iter
,
hb_enable_if
(
hb_is_iterator
(
Iter
))>
hb_enable_if
(
hb_is_iterator
(
Iter
))>
...
@@ -527,7 +529,7 @@ static const struct
...
@@ -527,7 +529,7 @@ static const struct
for
(;
it
;
++
it
)
for
(;
it
;
++
it
)
(
void
)
*
it
;
(
void
)
*
it
;
}
}
}
hb_drain
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_drain
)
;
/* hb_unzip(): unzip and sink to two sinks. */
/* hb_unzip(): unzip and sink to two sinks. */
...
@@ -553,7 +555,7 @@ struct hb_unzip_t
...
@@ -553,7 +555,7 @@ struct hb_unzip_t
Sink1
s1
;
Sink1
s1
;
Sink2
s2
;
Sink2
s2
;
};
};
st
atic
const
st
ruct
struct
{
{
template
<
typename
Sink1
,
typename
Sink2
>
hb_unzip_t
<
Sink1
,
Sink2
>
template
<
typename
Sink1
,
typename
Sink2
>
hb_unzip_t
<
Sink1
,
Sink2
>
operator
()
(
Sink1
&&
s1
,
Sink2
&&
s2
)
const
operator
()
(
Sink1
&&
s1
,
Sink2
&&
s2
)
const
...
@@ -562,12 +564,12 @@ static const struct
...
@@ -562,12 +564,12 @@ static const struct
template
<
typename
Sink1
,
typename
Sink2
>
hb_unzip_t
<
Sink1
&
,
Sink2
&>
template
<
typename
Sink1
,
typename
Sink2
>
hb_unzip_t
<
Sink1
&
,
Sink2
&>
operator
()
(
Sink1
*
s1
,
Sink2
*
s2
)
const
operator
()
(
Sink1
*
s1
,
Sink2
*
s2
)
const
{
return
hb_unzip_t
<
Sink1
&
,
Sink2
&>
(
*
s1
,
*
s2
);
}
{
return
hb_unzip_t
<
Sink1
&
,
Sink2
&>
(
*
s1
,
*
s2
);
}
}
hb_unzip
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_unzip
)
;
/* hb-all, hb-any, hb-none. */
/* hb-all, hb-any, hb-none. */
st
atic
const
st
ruct
struct
{
{
template
<
typename
Iterable
,
template
<
typename
Iterable
,
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
...
@@ -579,9 +581,8 @@ static const struct
...
@@ -579,9 +581,8 @@ static const struct
return
false
;
return
false
;
return
true
;
return
true
;
}
}
}
hb_all
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_all
);
struct
static
const
struct
{
{
template
<
typename
Iterable
,
template
<
typename
Iterable
,
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
...
@@ -593,9 +594,8 @@ static const struct
...
@@ -593,9 +594,8 @@ static const struct
return
true
;
return
true
;
return
false
;
return
false
;
}
}
}
hb_any
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_any
);
struct
static
const
struct
{
{
template
<
typename
Iterable
,
template
<
typename
Iterable
,
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
hb_enable_if
(
hb_is_iterable
(
Iterable
))>
...
@@ -607,7 +607,7 @@ static const struct
...
@@ -607,7 +607,7 @@ static const struct
return
false
;
return
false
;
return
true
;
return
true
;
}
}
}
hb_none
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_none
)
;
/*
/*
* Algorithms operating on iterators.
* Algorithms operating on iterators.
...
...
src/hb-meta.hh
浏览文件 @
02d864aa
...
@@ -34,18 +34,22 @@
...
@@ -34,18 +34,22 @@
* C++ template meta-programming & fundamentals used with them.
* C++ template meta-programming & fundamentals used with them.
*/
*/
#define HB_FUNCOBJ(x) static_const x HB_UNUSED
template
<
typename
T
>
static
inline
T
*
struct
hb_addressof
(
const
T
&
arg
)
{
{
template
<
typename
T
>
T
*
operator
()
(
const
T
&
arg
)
const
{
#pragma GCC diagnostic push
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-align"
#pragma GCC diagnostic ignored "-Wcast-align"
/* https://en.cppreference.com/w/cpp/memory/addressof */
/* https://en.cppreference.com/w/cpp/memory/addressof */
return
reinterpret_cast
<
T
*>
(
return
reinterpret_cast
<
T
*>
(
&
const_cast
<
char
&>
(
&
const_cast
<
char
&>
(
reinterpret_cast
<
const
volatile
char
&>
(
arg
)));
reinterpret_cast
<
const
volatile
char
&>
(
arg
)));
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
}
}
}
HB_FUNCOBJ
(
hb_addressof
);
template
<
typename
T
>
static
inline
T
hb_declval
();
template
<
typename
T
>
static
inline
T
hb_declval
();
#define hb_declval(T) (hb_declval<T> ())
#define hb_declval(T) (hb_declval<T> ())
...
@@ -63,13 +67,13 @@ template <typename T> struct hb_match_pointer<T *> { typedef T type; enum { valu
...
@@ -63,13 +67,13 @@ template <typename T> struct hb_match_pointer<T *> { typedef T type; enum { valu
#define hb_remove_pointer(T) typename hb_match_pointer<T>::type
#define hb_remove_pointer(T) typename hb_match_pointer<T>::type
#define hb_is_pointer(T) hb_match_pointer<T>::value
#define hb_is_pointer(T) hb_match_pointer<T>::value
st
atic
const
st
ruct
struct
{
{
template
<
typename
T
>
template
<
typename
T
>
T
operator
()
(
T
v
)
const
{
return
v
;
}
T
operator
()
(
T
v
)
const
{
return
v
;
}
template
<
typename
T
>
template
<
typename
T
>
T
&
operator
()
(
T
*
v
)
const
{
return
*
v
;
}
T
&
operator
()
(
T
*
v
)
const
{
return
*
v
;
}
}
hb_deref_pointer
HB_UNUSED
;
}
HB_FUNCOBJ
(
hb_deref_pointer
)
;
/* std::move and std::forward */
/* std::move and std::forward */
...
...
src/hb.hh
浏览文件 @
02d864aa
...
@@ -260,6 +260,13 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
...
@@ -260,6 +260,13 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
# endif
# endif
#endif
#endif
/* https://github.com/harfbuzz/harfbuzz/issues/1651 */
#if defined(__clang__) && __clang_major__ < 10
#define static_const static
#else
#define static_const static const
#endif
#if defined(__GNUC__) && (__GNUC__ >= 3)
#if defined(__GNUC__) && (__GNUC__ >= 3)
#define HB_FUNC __PRETTY_FUNCTION__
#define HB_FUNC __PRETTY_FUNCTION__
#elif defined(_MSC_VER)
#elif defined(_MSC_VER)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录