Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Third Party Harfbuzz
提交
fa877703
T
Third Party Harfbuzz
项目概览
OpenHarmony
/
Third Party Harfbuzz
12 个月 前同步成功
通知
0
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
fa877703
编写于
2月 14, 2018
作者:
R
Rod Sheeter
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[subset] First pass at hmtx
上级
e5edcc81
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
422 addition
and
79 deletion
+422
-79
src/hb-ot-cmap-table.hh
src/hb-ot-cmap-table.hh
+10
-9
src/hb-ot-hhea-table.hh
src/hb-ot-hhea-table.hh
+3
-3
src/hb-ot-hmtx-table.hh
src/hb-ot-hmtx-table.hh
+144
-19
src/hb-ot-maxp-table.hh
src/hb-ot-maxp-table.hh
+4
-4
src/hb-ot-os2-table.hh
src/hb-ot-os2-table.hh
+4
-4
src/hb-subset-glyf.cc
src/hb-subset-glyf.cc
+2
-3
src/hb-subset-glyf.hh
src/hb-subset-glyf.hh
+0
-1
src/hb-subset-plan.cc
src/hb-subset-plan.cc
+12
-0
src/hb-subset-plan.hh
src/hb-subset-plan.hh
+10
-0
src/hb-subset-private.hh
src/hb-subset-private.hh
+11
-0
src/hb-subset.cc
src/hb-subset.cc
+49
-36
test/api/Makefile.am
test/api/Makefile.am
+7
-0
test/api/fonts/Inconsolata-Regular.ab.ttf
test/api/fonts/Inconsolata-Regular.ab.ttf
+0
-0
test/api/fonts/Inconsolata-Regular.abc.ttf
test/api/fonts/Inconsolata-Regular.abc.ttf
+0
-0
test/api/fonts/Inconsolata-Regular.abc.widerc.ttf
test/api/fonts/Inconsolata-Regular.abc.widerc.ttf
+0
-0
test/api/fonts/Inconsolata-Regular.ac.ttf
test/api/fonts/Inconsolata-Regular.ac.ttf
+0
-0
test/api/fonts/Inconsolata-Regular.ac.widerc.ttf
test/api/fonts/Inconsolata-Regular.ac.widerc.ttf
+0
-0
test/api/fonts/README
test/api/fonts/README
+2
-0
test/api/test-subset-hmtx.c
test/api/test-subset-hmtx.c
+164
-0
未找到文件。
src/hb-ot-cmap-table.hh
浏览文件 @
fa877703
...
...
@@ -599,13 +599,13 @@ struct cmap
return
true
;
}
inline
hb_b
lob_t
*
subset
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
source
)
const
inline
hb_b
ool_t
subset
(
hb_subset_plan_t
*
plan
)
const
{
hb_auto_array_t
<
CmapSubtableLongGroup
>
groups
;
if
(
unlikely
(
!
populate_groups
(
plan
,
&
groups
)))
{
return
nullptr
;
return
false
;
}
// We now know how big our blob needs to be
...
...
@@ -617,21 +617,22 @@ struct cmap
void
*
dest
=
calloc
(
dest_sz
,
1
);
if
(
unlikely
(
!
dest
))
{
DEBUG_MSG
(
SUBSET
,
nullptr
,
"Unable to alloc %ld for cmap subset output"
,
dest_sz
);
return
nullptr
;
return
false
;
}
if
(
unlikely
(
!
_subset
(
groups
,
dest_sz
,
dest
)))
{
free
(
dest
);
return
nullptr
;
return
false
;
}
// all done, write the blob into dest
return
hb_blob_create
((
const
char
*
)
dest
,
dest_sz
,
HB_MEMORY_MODE_READONLY
,
/* userdata */
nullptr
,
free
);
hb_blob_t
*
cmap_prime
=
hb_blob_create
((
const
char
*
)
dest
,
dest_sz
,
HB_MEMORY_MODE_READONLY
,
/* userdata */
nullptr
,
free
);
return
hb_subset_plan_add_table
(
plan
,
HB_OT_TAG_cmap
,
cmap_prime
);
}
struct
accelerator_t
...
...
src/hb-ot-hhea-table.hh
浏览文件 @
fa877703
...
...
@@ -41,7 +41,7 @@ namespace OT {
#define HB_OT_TAG_hhea HB_TAG('h','h','e','a')
#define HB_OT_TAG_vhea HB_TAG('v','h','e','a')
template
<
typename
T
>
struct
_hea
{
inline
bool
sanitize
(
hb_sanitize_context_t
*
c
)
const
...
...
@@ -84,10 +84,10 @@ struct _hea
DEFINE_SIZE_STATIC
(
36
);
};
struct
hhea
:
_hea
{
struct
hhea
:
_hea
<
hhea
>
{
static
const
hb_tag_t
tableTag
=
HB_OT_TAG_hhea
;
};
struct
vhea
:
_hea
{
struct
vhea
:
_hea
<
vhea
>
{
static
const
hb_tag_t
tableTag
=
HB_OT_TAG_vhea
;
};
...
...
src/hb-ot-hmtx-table.hh
浏览文件 @
fa877703
...
...
@@ -53,7 +53,7 @@ struct LongMetric
DEFINE_SIZE_STATIC
(
4
);
};
template
<
typename
T
>
template
<
typename
T
,
typename
H
>
struct
hmtxvmtx
{
inline
bool
sanitize
(
hb_sanitize_context_t
*
c
)
const
...
...
@@ -64,8 +64,129 @@ struct hmtxvmtx
return_trace
(
true
);
}
inline
bool
subset_update_header
(
hb_subset_plan_t
*
plan
,
unsigned
int
num_hmetrics
)
const
{
/* alloc the new table */
size_t
dest_sz
=
sizeof
(
H
);
void
*
dest
=
(
void
*
)
calloc
(
dest_sz
,
1
);
if
(
unlikely
(
!
dest
))
{
return
false
;
}
hb_blob_t
*
src_blob
=
OT
::
Sanitizer
<
H
>
().
sanitize
(
plan
->
source
->
reference_table
(
T
::
tableTag
));
if
(
unlikely
(
!
src_blob
))
{
return
false
;
}
unsigned
int
src_length
;
const
char
*
src_raw
=
hb_blob_get_data
(
src_blob
,
&
src_length
);
memcpy
(
dest
,
src_raw
,
src_length
);
H
*
table
=
(
H
*
)
dest
;
table
->
numberOfLongMetrics
.
set
(
num_hmetrics
);
hb_blob_t
*
dest_blob
=
hb_blob_create
((
const
char
*
)
dest
,
dest_sz
,
HB_MEMORY_MODE_READONLY
,
/* userdata */
nullptr
,
free
);
return
hb_subset_plan_add_table
(
plan
,
H
::
tableTag
,
dest_blob
);
}
inline
bool
subset
(
hb_subset_plan_t
*
plan
)
const
{
typename
T
::
accelerator_t
_mtx
;
_mtx
.
init
(
plan
->
source
);
/* All the trailing glyphs with the same advance can use one LongMetric
* and just keep LSB */
hb_prealloced_array_t
<
hb_codepoint_t
>
&
gids
=
plan
->
gids_to_retain_sorted
;
unsigned
int
num_advances
=
gids
.
len
;
unsigned
int
last_advance
=
_mtx
.
get_advance
(
gids
[
num_advances
-
1
]);
while
(
num_advances
>
1
&&
last_advance
==
_mtx
.
get_advance
(
gids
[
num_advances
-
2
]))
{
num_advances
--
;
}
/* alloc the new table */
size_t
dest_sz
=
num_advances
*
4
+
(
gids
.
len
-
num_advances
)
*
2
;
void
*
dest
=
(
void
*
)
calloc
(
dest_sz
,
1
);
if
(
unlikely
(
!
dest
))
{
return
false
;
}
DEBUG_MSG
(
SUBSET
,
nullptr
,
"%c%c%c%c in src has %d advances, %d lsbs"
,
HB_UNTAG
(
T
::
tableTag
),
_mtx
.
num_advances
,
_mtx
.
num_metrics
-
_mtx
.
num_advances
);
DEBUG_MSG
(
SUBSET
,
nullptr
,
"%c%c%c%c in dest has %d advances, %d lsbs, %d bytes"
,
HB_UNTAG
(
T
::
tableTag
),
num_advances
,
gids
.
len
-
num_advances
,
dest_sz
);
const
char
*
source_table
=
hb_blob_get_data
(
_mtx
.
blob
,
nullptr
);
// Copy everything over
LongMetric
*
old_metrics
=
(
LongMetric
*
)
source_table
;
FWORD
*
lsbs
=
(
FWORD
*
)
(
old_metrics
+
_mtx
.
num_advances
);
char
*
dest_pos
=
(
char
*
)
dest
;
for
(
unsigned
int
i
=
0
;
i
<
gids
.
len
;
i
++
)
{
/* the last metric or the one for gids[i] */
LongMetric
*
src_metric
=
old_metrics
+
MIN
(
_mtx
.
num_advances
-
1
,
gids
[
i
]);
if
(
gids
[
i
]
<
_mtx
.
num_advances
)
{
/* src is a LongMetric */
if
(
i
<
num_advances
)
{
/* dest is a LongMetric, copy it */
*
((
LongMetric
*
)
dest_pos
)
=
*
src_metric
;
}
else
{
/* dest just lsb */
*
((
FWORD
*
)
dest_pos
)
=
src_metric
->
lsb
;
}
}
else
{
FWORD
src_lsb
=
*
(
lsbs
+
gids
[
i
]
-
_mtx
.
num_advances
);
if
(
i
<
num_advances
)
{
/* dest needs a full LongMetric */
LongMetric
*
metric
=
(
LongMetric
*
)
dest_pos
;
metric
->
advance
=
src_metric
->
advance
;
metric
->
lsb
=
src_lsb
;
}
else
{
/* dest just needs an lsb */
*
((
FWORD
*
)
dest_pos
)
=
src_lsb
;
}
}
dest_pos
+=
(
i
<
num_advances
?
4
:
2
);
}
_mtx
.
fini
();
// Amend header num hmetrics
if
(
unlikely
(
!
subset_update_header
(
plan
,
num_advances
)))
{
free
(
dest
);
return
false
;
}
hb_blob_t
*
result
=
hb_blob_create
((
const
char
*
)
dest
,
dest_sz
,
HB_MEMORY_MODE_READONLY
,
/* userdata */
nullptr
,
free
);
return
hb_subset_plan_add_table
(
plan
,
T
::
tableTag
,
result
);
}
struct
accelerator_t
{
friend
struct
hmtxvmtx
;
inline
void
init
(
hb_face_t
*
face
,
unsigned
int
default_advance_
=
0
)
{
...
...
@@ -87,8 +208,8 @@ struct hmtxvmtx
hb_blob_destroy
(
os2_blob
);
}
hb_blob_t
*
_hea_blob
=
Sanitizer
<
_hea
>
().
sanitize
(
face
->
reference_table
(
T
::
header
Tag
));
const
_hea
*
_hea_table
=
Sanitizer
<
_hea
>::
lock_instance
(
_hea_blob
);
hb_blob_t
*
_hea_blob
=
Sanitizer
<
H
>
().
sanitize
(
face
->
reference_table
(
H
::
table
Tag
));
const
H
*
_hea_table
=
Sanitizer
<
H
>::
lock_instance
(
_hea_blob
);
num_advances
=
_hea_table
->
numberOfLongMetrics
;
if
(
!
got_font_extents
)
{
...
...
@@ -129,22 +250,27 @@ struct hmtxvmtx
hb_blob_destroy
(
var_blob
);
}
inline
unsigned
int
get_advance
(
hb_codepoint_t
glyph
,
hb_font_t
*
font
)
const
inline
unsigned
int
get_advance
(
hb_codepoint_t
glyph
)
const
{
if
(
unlikely
(
glyph
>=
num_metrics
))
{
/* If num_metrics is zero, it means we don't have the metrics table
* for this direction: return default advance. Otherwise, it means that the
* glyph index is out of bound: return zero. */
if
(
num_metrics
)
return
0
;
else
return
default_advance
;
/* If num_metrics is zero, it means we don't have the metrics table
* for this direction: return default advance. Otherwise, it means that the
* glyph index is out of bound: return zero. */
if
(
num_metrics
)
return
0
;
else
return
default_advance
;
}
return
table
->
longMetric
[
MIN
(
glyph
,
(
uint32_t
)
num_advances
-
1
)].
advance
+
(
font
->
num_coords
?
var_table
->
get_advance_var
(
glyph
,
font
->
coords
,
font
->
num_coords
)
:
0
);
// TODO Optimize?!
return
table
->
longMetric
[
MIN
(
glyph
,
(
uint32_t
)
num_advances
-
1
)].
advance
;
}
inline
unsigned
int
get_advance
(
hb_codepoint_t
glyph
,
hb_font_t
*
font
)
const
{
return
get_advance
(
glyph
)
+
(
font
->
num_coords
?
var_table
->
get_advance_var
(
glyph
,
font
->
coords
,
font
->
num_coords
)
:
0
);
// TODO Optimize?!
}
public:
...
...
@@ -153,11 +279,12 @@ struct hmtxvmtx
unsigned
short
descender
;
unsigned
short
line_gap
;
pr
ivate
:
pr
otected
:
unsigned
int
num_metrics
;
unsigned
int
num_advances
;
unsigned
int
default_advance
;
private:
const
hmtxvmtx
*
table
;
hb_blob_t
*
blob
;
const
HVARVVAR
*
var_table
;
...
...
@@ -190,15 +317,13 @@ struct hmtxvmtx
DEFINE_SIZE_ARRAY
(
0
,
longMetric
);
};
struct
hmtx
:
hmtxvmtx
<
hmtx
>
{
struct
hmtx
:
hmtxvmtx
<
hmtx
,
hhea
>
{
static
const
hb_tag_t
tableTag
=
HB_OT_TAG_hmtx
;
static
const
hb_tag_t
headerTag
=
HB_OT_TAG_hhea
;
static
const
hb_tag_t
variationsTag
=
HB_OT_TAG_HVAR
;
static
const
hb_tag_t
os2Tag
=
HB_OT_TAG_os2
;
};
struct
vmtx
:
hmtxvmtx
<
vmtx
>
{
struct
vmtx
:
hmtxvmtx
<
vmtx
,
vhea
>
{
static
const
hb_tag_t
tableTag
=
HB_OT_TAG_vmtx
;
static
const
hb_tag_t
headerTag
=
HB_OT_TAG_vhea
;
static
const
hb_tag_t
variationsTag
=
HB_OT_TAG_VVAR
;
static
const
hb_tag_t
os2Tag
=
HB_TAG_NONE
;
};
...
...
src/hb-ot-maxp-table.hh
浏览文件 @
fa877703
...
...
@@ -61,21 +61,21 @@ struct maxp
(
version
.
major
==
0
&&
version
.
minor
==
0x5000u
)));
}
inline
hb_b
lob_t
*
subset
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
source
)
const
inline
hb_b
ool_t
subset
(
hb_subset_plan_t
*
plan
)
const
{
hb_blob_t
*
maxp_blob
=
OT
::
Sanitizer
<
OT
::
maxp
>
().
sanitize
(
hb_face_reference_table
(
source
,
HB_OT_TAG_maxp
));
hb_blob_t
*
maxp_blob
=
OT
::
Sanitizer
<
OT
::
maxp
>
().
sanitize
(
hb_face_reference_table
(
plan
->
source
,
HB_OT_TAG_maxp
));
hb_blob_t
*
maxp_prime_blob
=
hb_blob_create_sub_blob
(
maxp_blob
,
0
,
-
1
);
hb_blob_destroy
(
maxp_blob
);
OT
::
maxp
*
maxp_prime
=
(
OT
::
maxp
*
)
hb_blob_get_data_writable
(
maxp_prime_blob
,
nullptr
);
if
(
unlikely
(
!
maxp_prime
))
{
hb_blob_destroy
(
maxp_prime_blob
);
return
nullptr
;
return
false
;
}
maxp_prime
->
set_num_glyphs
(
plan
->
gids_to_retain_sorted
.
len
);
return
maxp_prime_blob
;
return
hb_subset_plan_add_table
(
plan
,
HB_OT_TAG_maxp
,
maxp_prime_blob
)
;
}
/* We only implement version 0.5 as none of the extra fields in version 1.0 are useful. */
...
...
src/hb-ot-os2-table.hh
浏览文件 @
fa877703
...
...
@@ -49,16 +49,16 @@ struct os2
return_trace
(
c
->
check_struct
(
this
));
}
inline
hb_b
lob_t
*
subset
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
source
)
const
inline
hb_b
ool_t
subset
(
hb_subset_plan_t
*
plan
)
const
{
hb_blob_t
*
os2_blob
=
OT
::
Sanitizer
<
OT
::
os2
>
().
sanitize
(
hb_face_reference_table
(
source
,
HB_OT_TAG_os2
));
hb_blob_t
*
os2_blob
=
OT
::
Sanitizer
<
OT
::
os2
>
().
sanitize
(
hb_face_reference_table
(
plan
->
source
,
HB_OT_TAG_os2
));
hb_blob_t
*
os2_prime_blob
=
hb_blob_create_sub_blob
(
os2_blob
,
0
,
-
1
);
hb_blob_destroy
(
os2_blob
);
OT
::
os2
*
os2_prime
=
(
OT
::
os2
*
)
hb_blob_get_data_writable
(
os2_prime_blob
,
nullptr
);
if
(
unlikely
(
!
os2_prime
))
{
hb_blob_destroy
(
os2_prime_blob
);
return
nullptr
;
return
false
;
}
uint16_t
min_cp
,
max_cp
;
...
...
@@ -66,7 +66,7 @@ struct os2
os2_prime
->
usFirstCharIndex
.
set
(
min_cp
);
os2_prime
->
usLastCharIndex
.
set
(
max_cp
);
return
os2_prime_blob
;
return
hb_subset_plan_add_table
(
plan
,
HB_OT_TAG_os2
,
os2_prime_blob
)
;
}
static
inline
void
find_min_and_max_codepoint
(
hb_subset_plan_t
*
plan
,
...
...
src/hb-subset-glyf.cc
浏览文件 @
fa877703
...
...
@@ -157,16 +157,15 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t &glyf,
**/
bool
hb_subset_glyf_and_loca
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
face
,
bool
*
use_short_loca
,
/* OUT */
hb_blob_t
**
glyf_prime
,
/* OUT */
hb_blob_t
**
loca_prime
/* OUT */
)
{
hb_blob_t
*
glyf_blob
=
OT
::
Sanitizer
<
OT
::
glyf
>
().
sanitize
(
fa
ce
->
reference_table
(
HB_OT_TAG_glyf
));
hb_blob_t
*
glyf_blob
=
OT
::
Sanitizer
<
OT
::
glyf
>
().
sanitize
(
plan
->
sour
ce
->
reference_table
(
HB_OT_TAG_glyf
));
const
char
*
glyf_data
=
hb_blob_get_data
(
glyf_blob
,
nullptr
);
OT
::
glyf
::
accelerator_t
glyf
;
glyf
.
init
(
fa
ce
);
glyf
.
init
(
plan
->
sour
ce
);
bool
result
=
_hb_subset_glyf_and_loca
(
glyf
,
glyf_data
,
plan
->
gids_to_retain_sorted
,
...
...
src/hb-subset-glyf.hh
浏览文件 @
fa877703
...
...
@@ -33,7 +33,6 @@
HB_INTERNAL
bool
hb_subset_glyf_and_loca
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
face
,
bool
*
use_short_loca
,
/* OUT */
hb_blob_t
**
glyf_prime
/* OUT */
,
hb_blob_t
**
loca_prime
/* OUT */
);
...
...
src/hb-subset-plan.cc
浏览文件 @
fa877703
...
...
@@ -72,6 +72,14 @@ hb_subset_plan_new_gid_for_old_id (hb_subset_plan_t *plan,
return
false
;
}
hb_bool_t
hb_subset_plan_add_table
(
hb_subset_plan_t
*
plan
,
hb_tag_t
tag
,
hb_blob_t
*
contents
)
{
return
hb_subset_face_add_table
(
plan
->
dest
,
tag
,
contents
);
}
static
void
_populate_codepoints
(
hb_set_t
*
input_codepoints
,
hb_prealloced_array_t
<
hb_codepoint_t
>&
plan_codepoints
)
...
...
@@ -110,6 +118,7 @@ _populate_gids_to_retain (hb_face_t *face,
*
(
old_gids
.
push
())
=
gid
;
}
/* Generally there shouldn't be any */
while
(
bad_indices
.
len
>
0
)
{
unsigned
int
i
=
bad_indices
[
bad_indices
.
len
-
1
];
bad_indices
.
pop
();
...
...
@@ -154,12 +163,15 @@ hb_subset_plan_create (hb_face_t *face,
plan
->
codepoints
.
init
();
plan
->
gids_to_retain
.
init
();
plan
->
gids_to_retain_sorted
.
init
();
plan
->
source
=
face
;
plan
->
dest
=
hb_subset_face_create
();
_populate_codepoints
(
input
->
unicodes
,
plan
->
codepoints
);
_populate_gids_to_retain
(
face
,
plan
->
codepoints
,
plan
->
gids_to_retain
,
plan
->
gids_to_retain_sorted
);
return
plan
;
}
...
...
src/hb-subset-plan.hh
浏览文件 @
fa877703
...
...
@@ -38,9 +38,14 @@ struct hb_subset_plan_t {
// TODO(Q1) actual map, drop this crap
// Look at me ma, I'm a poor mans map codepoint : new gid
// codepoints is sorted and aligned with gids_to_retain.
// TODO Also you should init/fini those arrays
hb_prealloced_array_t
<
hb_codepoint_t
>
codepoints
;
hb_prealloced_array_t
<
hb_codepoint_t
>
gids_to_retain
;
hb_prealloced_array_t
<
hb_codepoint_t
>
gids_to_retain_sorted
;
// Plan is only good for a specific source/dest so keep them with it
hb_face_t
*
source
;
hb_face_t
*
dest
;
};
typedef
struct
hb_subset_plan_t
hb_subset_plan_t
;
...
...
@@ -60,6 +65,11 @@ hb_subset_plan_new_gid_for_codepoint(hb_subset_plan_t *plan,
hb_codepoint_t
codepont
,
hb_codepoint_t
*
new_gid
/* OUT */
);
HB_INTERNAL
hb_bool_t
hb_subset_plan_add_table
(
hb_subset_plan_t
*
plan
,
hb_tag_t
tag
,
hb_blob_t
*
contents
);
HB_INTERNAL
void
hb_subset_plan_destroy
(
hb_subset_plan_t
*
plan
);
...
...
src/hb-subset-private.hh
浏览文件 @
fa877703
...
...
@@ -34,6 +34,8 @@
#include "hb-font-private.hh"
typedef
struct
hb_subset_face_data_t
hb_subset_face_data_t
;
struct
hb_subset_input_t
{
hb_object_header_t
header
;
ASSERT_POD
();
...
...
@@ -50,4 +52,13 @@ struct hb_subset_input_t {
*/
};
HB_INTERNAL
hb_face_t
*
hb_subset_face_create
(
void
);
HB_INTERNAL
hb_bool_t
hb_subset_face_add_table
(
hb_face_t
*
face
,
hb_tag_t
tag
,
hb_blob_t
*
blob
);
HB_INTERNAL
void
hb_subset_face_data_destroy
(
void
*
user_data
);
#endif
/* HB_SUBSET_PRIVATE_HH */
src/hb-subset.cc
浏览文件 @
fa877703
...
...
@@ -21,12 +21,14 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Garret Rieger, Rod Sheeter
, Behdad Esfahbod
* Google Author(s): Garret Rieger, Rod Sheeter
*/
#include "hb-object-private.hh"
#include "hb-open-type-private.hh"
#include "hb-private.hh"
#include "hb-subset-glyf.hh"
#include "hb-subset-private.hh"
#include "hb-subset-plan.hh"
...
...
@@ -35,6 +37,8 @@
#include "hb-ot-cmap-table.hh"
#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-hmtx-table.hh"
#include "hb-ot-maxp-table.hh"
#include "hb-ot-os2-table.hh"
...
...
@@ -76,13 +80,13 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile)
}
template
<
typename
TableType
>
static
hb_b
lob_t
*
_subset
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
source
)
static
hb_b
ool_t
_subset
(
hb_subset_plan_t
*
plan
)
{
OT
::
Sanitizer
<
TableType
>
sanitizer
;
hb_blob_t
*
source_blob
=
sanitizer
.
sanitize
(
source
->
reference_table
(
TableType
::
tableTag
));
hb_blob_t
*
source_blob
=
sanitizer
.
sanitize
(
plan
->
source
->
reference_table
(
TableType
::
tableTag
));
const
TableType
*
table
=
OT
::
Sanitizer
<
TableType
>::
lock_instance
(
source_blob
);
hb_b
lob_t
*
result
=
table
->
subset
(
plan
,
source
);
hb_b
ool_t
result
=
table
->
subset
(
plan
);
hb_blob_destroy
(
source_blob
);
...
...
@@ -124,8 +128,8 @@ _hb_subset_face_data_create (void)
return
data
;
}
static
void
_
hb_subset_face_data_destroy
(
void
*
user_data
)
void
hb_subset_face_data_destroy
(
void
*
user_data
)
{
hb_subset_face_data_t
*
data
=
(
hb_subset_face_data_t
*
)
user_data
;
...
...
@@ -188,7 +192,7 @@ _hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
return
nullptr
;
}
static
hb_face_t
*
hb_face_t
*
hb_subset_face_create
(
void
)
{
hb_subset_face_data_t
*
data
=
_hb_subset_face_data_create
();
...
...
@@ -196,13 +200,13 @@ hb_subset_face_create (void)
return
hb_face_create_for_tables
(
_hb_subset_face_reference_table
,
data
,
_
hb_subset_face_data_destroy
);
hb_subset_face_data_destroy
);
}
static
bool
hb_bool_t
hb_subset_face_add_table
(
hb_face_t
*
face
,
hb_tag_t
tag
,
hb_blob_t
*
blob
)
{
if
(
unlikely
(
face
->
destroy
!=
_
hb_subset_face_data_destroy
))
if
(
unlikely
(
face
->
destroy
!=
hb_subset_face_data_destroy
))
return
false
;
hb_subset_face_data_t
*
data
=
(
hb_subset_face_data_t
*
)
face
->
user_data
;
...
...
@@ -221,7 +225,7 @@ _add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_
{
hb_blob_t
*
head_blob
=
OT
::
Sanitizer
<
OT
::
head
>
().
sanitize
(
hb_face_reference_table
(
source
,
HB_OT_TAG_head
));
const
OT
::
head
*
head
=
OT
::
Sanitizer
<
OT
::
head
>::
lock_instance
(
head_blob
);
bool
has_head
=
(
head
!=
nullptr
);
hb_bool_t
has_head
=
(
head
!=
nullptr
);
if
(
has_head
)
{
OT
::
head
*
head_prime
=
(
OT
::
head
*
)
calloc
(
OT
::
head
::
static_size
,
1
);
...
...
@@ -242,7 +246,7 @@ _add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_
}
static
bool
_subset_glyf
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
source
,
hb_face_t
*
dest
)
_subset_glyf
(
hb_subset_plan_t
*
plan
)
{
hb_blob_t
*
glyf_prime
=
nullptr
;
hb_blob_t
*
loca_prime
=
nullptr
;
...
...
@@ -250,10 +254,10 @@ _subset_glyf (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
bool
success
=
true
;
bool
use_short_loca
=
false
;
// TODO(grieger): Migrate to subset function on the table like cmap.
if
(
hb_subset_glyf_and_loca
(
plan
,
source
,
&
use_short_loca
,
&
glyf_prime
,
&
loca_prime
))
{
success
=
success
&&
hb_subset_
face_add_table
(
dest
,
HB_OT_TAG_glyf
,
glyf_prime
);
success
=
success
&&
hb_subset_
face_add_table
(
dest
,
HB_OT_TAG_loca
,
loca_prime
);
success
=
success
&&
_add_head_and_set_loca_version
(
source
,
use_short_loca
,
dest
);
if
(
hb_subset_glyf_and_loca
(
plan
,
&
use_short_loca
,
&
glyf_prime
,
&
loca_prime
))
{
success
=
success
&&
hb_subset_
plan_add_table
(
plan
,
HB_OT_TAG_glyf
,
glyf_prime
);
success
=
success
&&
hb_subset_
plan_add_table
(
plan
,
HB_OT_TAG_loca
,
loca_prime
);
success
=
success
&&
_add_head_and_set_loca_version
(
plan
->
source
,
use_short_loca
,
plan
->
dest
);
}
else
{
success
=
false
;
}
...
...
@@ -265,39 +269,50 @@ _subset_glyf (hb_subset_plan_t *plan, hb_face_t *source, hb_face_t *dest)
static
bool
_subset_table
(
hb_subset_plan_t
*
plan
,
hb_face_t
*
source
,
hb_tag_t
tag
,
hb_blob_t
*
source_blob
,
hb_face_t
*
dest
)
hb_tag_t
tag
)
{
// TODO (grieger): Handle updating the head table (loca format + num glyphs)
DEBUG_MSG
(
SUBSET
,
nullptr
,
"begin subset %c%c%c%c"
,
HB_UNTAG
(
tag
));
hb_blob_t
*
dest_blob
;
bool
result
=
true
;
switch
(
tag
)
{
case
HB_OT_TAG_glyf
:
return
_subset_glyf
(
plan
,
source
,
dest
);
result
=
_subset_glyf
(
plan
);
break
;
case
HB_OT_TAG_head
:
// SKIP head, it's handled by glyf
result
=
true
;
break
;
case
HB_OT_TAG_hhea
:
// SKIP hhea, it's handled by hmtx
return
true
;
case
HB_OT_TAG_hmtx
:
result
=
_subset
<
const
OT
::
hmtx
>
(
plan
);
break
;
case
HB_OT_TAG_maxp
:
dest_blob
=
_subset
<
const
OT
::
maxp
>
(
plan
,
source
);
result
=
_subset
<
const
OT
::
maxp
>
(
plan
);
break
;
case
HB_OT_TAG_loca
:
// SKIP loca, it's handle by glyf
return
true
;
case
HB_OT_TAG_cmap
:
dest_blob
=
_subset
<
const
OT
::
cmap
>
(
plan
,
source
);
result
=
_subset
<
const
OT
::
cmap
>
(
plan
);
break
;
case
HB_OT_TAG_os2
:
dest_blob
=
_subset
<
const
OT
::
os2
>
(
plan
,
source
);
result
=
_subset
<
const
OT
::
os2
>
(
plan
);
break
;
default:
dest_blob
=
source_blob
;
hb_blob_t
*
source_table
=
hb_face_reference_table
(
plan
->
source
,
tag
);
if
(
likely
(
source_table
))
{
result
=
hb_subset_plan_add_table
(
plan
,
tag
,
source_table
);
}
else
{
result
=
false
;
}
break
;
}
DEBUG_MSG
(
SUBSET
,
nullptr
,
"subset %c%c%c%c %s"
,
HB_UNTAG
(
tag
),
dest_blob
?
"ok"
:
"FAILED"
);
if
(
unlikely
(
!
dest_blob
))
return
false
;
if
(
unlikely
(
!
hb_subset_face_add_table
(
dest
,
tag
,
dest_blob
)))
return
false
;
DEBUG_MSG
(
SUBSET
,
nullptr
,
"subset %c%c%c%c %s"
,
HB_UNTAG
(
tag
),
result
?
"ok"
:
"FAILED"
);
return
true
;
}
...
...
@@ -325,14 +340,13 @@ _should_drop_table(hb_tag_t tag)
**/
hb_face_t
*
hb_subset
(
hb_face_t
*
source
,
hb_subset_profile_t
*
profile
,
hb_subset_profile_t
*
profile
,
hb_subset_input_t
*
input
)
{
if
(
unlikely
(
!
profile
||
!
input
||
!
source
))
return
hb_face_get_empty
();
hb_subset_plan_t
*
plan
=
hb_subset_plan_create
(
source
,
profile
,
input
);
hb_face_t
*
dest
=
hb_subset_face_create
();
hb_tag_t
table_tags
[
32
];
unsigned
int
offset
=
0
,
count
;
bool
success
=
true
;
...
...
@@ -347,12 +361,11 @@ hb_subset (hb_face_t *source,
DEBUG_MSG
(
SUBSET
,
nullptr
,
"drop %c%c%c%c"
,
HB_UNTAG
(
tag
));
continue
;
}
hb_blob_t
*
blob
=
hb_face_reference_table
(
source
,
tag
);
success
=
success
&&
_subset_table
(
plan
,
source
,
tag
,
blob
,
dest
);
hb_blob_destroy
(
blob
);
success
=
success
&&
_subset_table
(
plan
,
tag
);
}
}
while
(
count
==
ARRAY_LENGTH
(
table_tags
));
hb_face_t
*
result
=
success
?
hb_face_reference
(
plan
->
dest
)
:
hb_face_get_empty
();
hb_subset_plan_destroy
(
plan
);
return
success
?
dest
:
hb_face_get_empty
()
;
return
result
;
}
test/api/Makefile.am
浏览文件 @
fa877703
...
...
@@ -31,6 +31,7 @@ TEST_PROGS = \
test-shape
\
test-subset-cmap
\
test-subset-glyf
\
test-subset-hmtx
\
test-subset-os2
\
test-unicode
\
test-version
\
...
...
@@ -39,6 +40,7 @@ TEST_PROGS = \
test_subset_LDADD
=
$(LDADD)
$(top_builddir)
/src/libharfbuzz-subset.la
test_subset_cmap_LDADD
=
$(LDADD)
$(top_builddir)
/src/libharfbuzz-subset.la
test_subset_glyf_LDADD
=
$(LDADD)
$(top_builddir)
/src/libharfbuzz-subset.la
test_subset_hmtx_LDADD
=
$(LDADD)
$(top_builddir)
/src/libharfbuzz-subset.la
test_subset_os2_LDADD
=
$(LDADD)
$(top_builddir)
/src/libharfbuzz-subset.la
test_unicode_CPPFLAGS
=
\
...
...
@@ -65,6 +67,11 @@ TEST_PROGS += \
test_ot_math_LDADD
=
$(LDADD)
$(FREETYPE_LIBS)
test_ot_math_CPPFLAGS
=
$(AM_CPPFLAGS)
$(FREETYPE_CFLAGS)
EXTRA_DIST
+=
\
fonts/Inconsolata-Regular.ab.ttf
\
fonts/Inconsolata-Regular.abc.ttf
\
fonts/Inconsolata-Regular.abc.widerc.ttf
\
fonts/Inconsolata-Regular.ac.ttf
\
fonts/Inconsolata-Regular.ac.widerc.ttf
\
fonts/Roboto-Regular.abc.ttf
\
fonts/Roboto-Regular.ac.ttf
\
fonts/MathTestFontEmpty.otf
\
...
...
test/api/fonts/Inconsolata-Regular.ab.ttf
0 → 100644
浏览文件 @
fa877703
文件已添加
test/api/fonts/Inconsolata-Regular.abc.ttf
0 → 100644
浏览文件 @
fa877703
文件已添加
test/api/fonts/Inconsolata-Regular.abc.widerc.ttf
0 → 100644
浏览文件 @
fa877703
文件已添加
test/api/fonts/Inconsolata-Regular.ac.ttf
0 → 100644
浏览文件 @
fa877703
文件已添加
test/api/fonts/Inconsolata-Regular.ac.widerc.ttf
0 → 100644
浏览文件 @
fa877703
文件已添加
test/api/fonts/README
浏览文件 @
fa877703
cmap-format12-only files created by ttx & remove all other cmap entries
Inconsolata-Regular.abc.widerc.ttf has the hmtx width of "c" set to 600; everything else is 500. Subsetting out c should reduce numberOfHMetrics to 1.
test/api/test-subset-hmtx.c
0 → 100644
浏览文件 @
fa877703
/*
* Copyright © 2018 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that the
* above copyright notice and the following two paragraphs appear in
* all copies of this software.
*
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
* Google Author(s): Roderick Sheeter
*/
#include <stdbool.h>
#include "hb-test.h"
#include "hb-subset-test.h"
/* Unit tests for hmtx subsetting */
static
void
check_num_hmetrics
(
hb_face_t
*
face
,
uint16_t
expected_num_hmetrics
)
{
hb_blob_t
*
hhea_blob
=
hb_face_reference_table
(
face
,
HB_TAG
(
'h'
,
'h'
,
'e'
,
'a'
));
hb_blob_t
*
hmtx_blob
=
hb_face_reference_table
(
face
,
HB_TAG
(
'h'
,
'm'
,
't'
,
'x'
));
// TODO I sure wish I could just use the hmtx table struct!
unsigned
int
hmtx_len
=
hb_blob_get_length
(
hmtx_blob
);
unsigned
int
hhea_len
;
uint8_t
*
raw_hhea
=
(
uint8_t
*
)
hb_blob_get_data
(
hhea_blob
,
&
hhea_len
);
uint16_t
num_hmetrics
=
(
raw_hhea
[
hhea_len
-
2
]
<<
8
)
+
raw_hhea
[
hhea_len
-
1
];
g_assert_cmpuint
(
expected_num_hmetrics
,
==
,
num_hmetrics
);
hb_blob_destroy
(
hhea_blob
);
hb_blob_destroy
(
hmtx_blob
);
}
static
void
test_subset_hmtx_simple_subset
(
void
)
{
hb_face_t
*
face_abc
=
hb_subset_test_open_font
(
"fonts/Roboto-Regular.abc.ttf"
);
hb_face_t
*
face_ac
=
hb_subset_test_open_font
(
"fonts/Roboto-Regular.ac.ttf"
);
hb_set_t
*
codepoints
=
hb_set_create
();
hb_set_add
(
codepoints
,
'a'
);
hb_set_add
(
codepoints
,
'c'
);
hb_face_t
*
face_abc_subset
=
hb_subset_test_create_subset
(
face_abc
,
codepoints
);
hb_set_destroy
(
codepoints
);
check_num_hmetrics
(
face_abc_subset
,
3
);
/* nothing has same width */
hb_subset_test_check
(
face_ac
,
face_abc_subset
,
HB_TAG
(
'h'
,
'm'
,
't'
,
'x'
));
hb_face_destroy
(
face_abc_subset
);
hb_face_destroy
(
face_abc
);
hb_face_destroy
(
face_ac
);
}
static
void
test_subset_hmtx_monospace
(
void
)
{
hb_face_t
*
face_abc
=
hb_subset_test_open_font
(
"fonts/Inconsolata-Regular.abc.ttf"
);
hb_face_t
*
face_ac
=
hb_subset_test_open_font
(
"fonts/Inconsolata-Regular.ac.ttf"
);
hb_set_t
*
codepoints
=
hb_set_create
();
hb_set_add
(
codepoints
,
'a'
);
hb_set_add
(
codepoints
,
'c'
);
hb_face_t
*
face_abc_subset
=
hb_subset_test_create_subset
(
face_abc
,
codepoints
);
hb_set_destroy
(
codepoints
);
check_num_hmetrics
(
face_abc_subset
,
1
);
/* everything has same width */
hb_subset_test_check
(
face_ac
,
face_abc_subset
,
HB_TAG
(
'h'
,
'm'
,
't'
,
'x'
));
// TODO hhea
hb_face_destroy
(
face_abc_subset
);
hb_face_destroy
(
face_abc
);
hb_face_destroy
(
face_ac
);
}
static
void
test_subset_hmtx_keep_num_metrics
(
void
)
{
hb_face_t
*
face_abc
=
hb_subset_test_open_font
(
"fonts/Inconsolata-Regular.abc.widerc.ttf"
);
hb_face_t
*
face_ac
=
hb_subset_test_open_font
(
"fonts/Inconsolata-Regular.ac.widerc.ttf"
);
hb_set_t
*
codepoints
=
hb_set_create
();
hb_set_add
(
codepoints
,
'a'
);
hb_set_add
(
codepoints
,
'c'
);
hb_face_t
*
face_abc_subset
=
hb_subset_test_create_subset
(
face_abc
,
codepoints
);
hb_set_destroy
(
codepoints
);
check_num_hmetrics
(
face_abc_subset
,
3
);
/* c is wider */
hb_subset_test_check
(
face_ac
,
face_abc_subset
,
HB_TAG
(
'h'
,
'm'
,
't'
,
'x'
));
hb_face_destroy
(
face_abc_subset
);
hb_face_destroy
(
face_abc
);
hb_face_destroy
(
face_ac
);
}
static
void
test_subset_hmtx_decrease_num_metrics
(
void
)
{
hb_face_t
*
face_abc
=
hb_subset_test_open_font
(
"fonts/Inconsolata-Regular.abc.widerc.ttf"
);
hb_face_t
*
face_ab
=
hb_subset_test_open_font
(
"fonts/Inconsolata-Regular.ab.ttf"
);
hb_set_t
*
codepoints
=
hb_set_create
();
hb_set_add
(
codepoints
,
'a'
);
hb_set_add
(
codepoints
,
'b'
);
hb_face_t
*
face_abc_subset
=
hb_subset_test_create_subset
(
face_abc
,
codepoints
);
hb_set_destroy
(
codepoints
);
check_num_hmetrics
(
face_abc_subset
,
1
);
/* everything left has same width */
hb_subset_test_check
(
face_ab
,
face_abc_subset
,
HB_TAG
(
'h'
,
'm'
,
't'
,
'x'
));
hb_face_destroy
(
face_abc_subset
);
hb_face_destroy
(
face_abc
);
hb_face_destroy
(
face_ab
);
}
static
void
test_subset_hmtx_noop
(
void
)
{
hb_face_t
*
face_abc
=
hb_subset_test_open_font
(
"fonts/Roboto-Regular.abc.ttf"
);
hb_set_t
*
codepoints
=
hb_set_create
();
hb_set_add
(
codepoints
,
'a'
);
hb_set_add
(
codepoints
,
'b'
);
hb_set_add
(
codepoints
,
'c'
);
hb_face_t
*
face_abc_subset
=
hb_subset_test_create_subset
(
face_abc
,
codepoints
);
hb_set_destroy
(
codepoints
);
check_num_hmetrics
(
face_abc_subset
,
4
);
/* nothing has same width */
hb_subset_test_check
(
face_abc
,
face_abc_subset
,
HB_TAG
(
'h'
,
'm'
,
't'
,
'x'
));
hb_face_destroy
(
face_abc_subset
);
hb_face_destroy
(
face_abc
);
}
int
main
(
int
argc
,
char
**
argv
)
{
hb_test_init
(
&
argc
,
&
argv
);
hb_test_add
(
test_subset_hmtx_simple_subset
);
hb_test_add
(
test_subset_hmtx_monospace
);
hb_test_add
(
test_subset_hmtx_keep_num_metrics
);
hb_test_add
(
test_subset_hmtx_decrease_num_metrics
);
hb_test_add
(
test_subset_hmtx_noop
);
return
hb_test_run
();
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录