Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
weixin_43355755
engine
提交
17e78fa8
E
engine
项目概览
weixin_43355755
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
17e78fa8
编写于
6月 12, 2015
作者:
R
Raph Levien
提交者:
Android (Google) Code Review
6月 12, 2015
浏览文件
操作
浏览文件
下载
差异文件
Merge "Increase hyphenation penalty for short last line" into mnc-dev
上级
4ea1cc82
abae97a3
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
39 addition
and
70 deletion
+39
-70
include/minikin/LineBreaker.h
include/minikin/LineBreaker.h
+2
-7
libs/minikin/LineBreaker.cpp
libs/minikin/LineBreaker.cpp
+37
-63
未找到文件。
include/minikin/LineBreaker.h
浏览文件 @
17e78fa8
...
...
@@ -200,9 +200,6 @@ class LineBreaker {
float
currentLineWidth
()
const
;
// compute shrink/stretch penalty for line
float
computeScore
(
float
delta
,
bool
atEnd
);
void
addWordBreak
(
size_t
offset
,
ParaWidth
preBreak
,
ParaWidth
postBreak
,
float
penalty
,
uint8_t
hyph
);
...
...
@@ -213,10 +210,7 @@ class LineBreaker {
void
computeBreaksGreedy
();
void
computeBreaksOptimal
();
// special case when LineWidth is constant (layout is rectangle)
void
computeBreaksOptimalRect
();
void
computeBreaksOptimal
(
bool
isRectangular
);
void
finishBreaksOptimal
();
...
...
@@ -241,6 +235,7 @@ class LineBreaker {
ParaWidth
mWidth
=
0
;
std
::
vector
<
Candidate
>
mCandidates
;
float
mLinePenalty
=
0.0
f
;
// the following are state for greedy breaker (updated while adding style runs)
size_t
mLastBreak
;
...
...
libs/minikin/LineBreaker.cpp
浏览文件 @
17e78fa8
...
...
@@ -37,6 +37,13 @@ const float SCORE_INFTY = std::numeric_limits<float>::max();
const
float
SCORE_OVERFULL
=
1e12
f
;
const
float
SCORE_DESPERATE
=
1e10
f
;
// Multiplier for hyphen penalty on last line.
const
float
LAST_LINE_PENALTY_MULTIPLIER
=
4.0
f
;
// Penalty assigned to each line break (to try to minimize number of lines)
// TODO: when we implement full justification (so spaces can shrink and stretch), this is
// probably not the most appropriate method.
const
float
LINE_PENALTY_MULTIPLIER
=
2.0
f
;
// Very long words trigger O(n^2) behavior in hyphenation, so we disable hyphenation for
// unreasonably long words. This is somewhat of a heuristic because extremely long words
// are possible in some languages. This does mean that very long real words can get
...
...
@@ -122,6 +129,8 @@ float LineBreaker::addStyleRun(MinikinPaint* paint, const FontCollection* typefa
if
(
mHyphenationFrequency
==
kHyphenationFrequency_Normal
)
{
hyphenPenalty
*=
4.0
;
// TODO: Replace with a better value after some testing
}
mLinePenalty
=
std
::
max
(
mLinePenalty
,
hyphenPenalty
*
LINE_PENALTY_MULTIPLIER
);
}
size_t
current
=
(
size_t
)
mBreakIterator
->
current
();
...
...
@@ -235,17 +244,6 @@ void LineBreaker::addWordBreak(size_t offset, ParaWidth preBreak, ParaWidth post
addCandidate
(
cand
);
}
// TODO: for justified text, refine with shrink/stretch
float
LineBreaker
::
computeScore
(
float
delta
,
bool
atEnd
)
{
if
(
delta
<
0
)
{
return
SCORE_OVERFULL
;
}
else
if
(
atEnd
&&
mStrategy
!=
kBreakStrategy_Balanced
)
{
return
0.0
;
}
else
{
return
delta
*
delta
;
}
}
// TODO performance: could avoid populating mCandidates if greedy only
void
LineBreaker
::
addCandidate
(
Candidate
cand
)
{
size_t
candIndex
=
mCandidates
.
size
();
...
...
@@ -320,75 +318,51 @@ void LineBreaker::finishBreaksOptimal() {
std
::
reverse
(
mFlags
.
begin
(),
mFlags
.
end
());
}
void
LineBreaker
::
computeBreaksOptimal
()
{
void
LineBreaker
::
computeBreaksOptimal
(
bool
isRectangle
)
{
size_t
active
=
0
;
size_t
nCand
=
mCandidates
.
size
();
float
width
=
mLineWidths
.
getLineWidth
(
0
);
for
(
size_t
i
=
1
;
i
<
nCand
;
i
++
)
{
bool
atEnd
=
i
==
nCand
-
1
;
float
best
=
SCORE_INFTY
;
size_t
bestPrev
=
0
;
size_t
lineNumberLast
=
0
;
size_t
lineNumberLast
=
mCandidates
[
active
].
lineNumber
;
float
width
=
mLineWidths
.
getLineWidth
(
lineNumberLast
);
if
(
!
isRectangle
)
{
size_t
lineNumberLast
=
mCandidates
[
active
].
lineNumber
;
width
=
mLineWidths
.
getLineWidth
(
lineNumberLast
);
}
ParaWidth
leftEdge
=
mCandidates
[
i
].
postBreak
-
width
;
float
bestHope
=
0
;
for
(
size_t
j
=
active
;
j
<
i
;
j
++
)
{
size_t
lineNumber
=
mCandidates
[
j
].
lineNumber
;
if
(
lineNumber
!=
lineNumberLast
)
{
float
widthNew
=
mLineWidths
.
getLineWidth
(
lineNumber
);
if
(
widthNew
!=
width
)
{
leftEdge
=
mCandidates
[
i
].
postBreak
-
width
;
bestHope
=
0
;
width
=
widthNew
;
if
(
!
isRectangle
)
{
size_t
lineNumber
=
mCandidates
[
j
].
lineNumber
;
if
(
lineNumber
!=
lineNumberLast
)
{
float
widthNew
=
mLineWidths
.
getLineWidth
(
lineNumber
);
if
(
widthNew
!=
width
)
{
leftEdge
=
mCandidates
[
i
].
postBreak
-
width
;
bestHope
=
0
;
width
=
widthNew
;
}
lineNumberLast
=
lineNumber
;
}
lineNumberLast
=
lineNumber
;
}
float
jScore
=
mCandidates
[
j
].
score
;
if
(
jScore
+
bestHope
>=
best
)
continue
;
float
delta
=
mCandidates
[
j
].
preBreak
-
leftEdge
;
float
widthScore
=
computeScore
(
delta
,
atEnd
);
// compute width score for line
float
widthScore
=
0.0
f
;
if
(
delta
<
0
)
{
active
=
j
+
1
;
widthScore
=
SCORE_OVERFULL
;
}
else
if
(
atEnd
&&
mStrategy
!=
kBreakStrategy_Balanced
)
{
// increase penalty for hyphen on last line
widthScore
=
LAST_LINE_PENALTY_MULTIPLIER
*
mCandidates
[
j
].
penalty
;
}
else
{
bestHope
=
widthScore
;
}
float
score
=
jScore
+
widthScore
;
if
(
score
<=
best
)
{
best
=
score
;
bestPrev
=
j
;
widthScore
=
delta
*
delta
;
}
}
mCandidates
[
i
].
score
=
best
+
mCandidates
[
i
].
penalty
;
mCandidates
[
i
].
prev
=
bestPrev
;
mCandidates
[
i
].
lineNumber
=
mCandidates
[
bestPrev
].
lineNumber
+
1
;
}
finishBreaksOptimal
();
}
void
LineBreaker
::
computeBreaksOptimalRect
()
{
size_t
active
=
0
;
size_t
nCand
=
mCandidates
.
size
();
float
width
=
mLineWidths
.
getLineWidth
(
0
);
for
(
size_t
i
=
1
;
i
<
nCand
;
i
++
)
{
bool
atEnd
=
i
==
nCand
-
1
;
float
best
=
SCORE_INFTY
;
size_t
bestPrev
=
0
;
// Width-based component of score increases as line gets shorter, so score will always be
// at least this.
float
bestHope
=
0
;
ParaWidth
leftEdge
=
mCandidates
[
i
].
postBreak
-
width
;
for
(
size_t
j
=
active
;
j
<
i
;
j
++
)
{
// TODO performance: can break if bestHope >= best; worth it?
float
jScore
=
mCandidates
[
j
].
score
;
if
(
jScore
+
bestHope
>=
best
)
continue
;
float
delta
=
mCandidates
[
j
].
preBreak
-
leftEdge
;
float
widthScore
=
computeScore
(
delta
,
atEnd
);
if
(
delta
<
0
)
{
active
=
j
+
1
;
}
else
{
...
...
@@ -401,8 +375,9 @@ void LineBreaker::computeBreaksOptimalRect() {
bestPrev
=
j
;
}
}
mCandidates
[
i
].
score
=
best
+
mCandidates
[
i
].
penalty
;
mCandidates
[
i
].
score
=
best
+
mCandidates
[
i
].
penalty
+
mLinePenalty
;
mCandidates
[
i
].
prev
=
bestPrev
;
mCandidates
[
i
].
lineNumber
=
mCandidates
[
bestPrev
].
lineNumber
+
1
;
}
finishBreaksOptimal
();
}
...
...
@@ -410,10 +385,8 @@ void LineBreaker::computeBreaksOptimalRect() {
size_t
LineBreaker
::
computeBreaks
()
{
if
(
mStrategy
==
kBreakStrategy_Greedy
)
{
computeBreaksGreedy
();
}
else
if
(
mLineWidths
.
isConstant
())
{
computeBreaksOptimalRect
();
}
else
{
computeBreaksOptimal
();
computeBreaksOptimal
(
mLineWidths
.
isConstant
()
);
}
return
mBreaks
.
size
();
}
...
...
@@ -438,6 +411,7 @@ void LineBreaker::finish() {
}
mStrategy
=
kBreakStrategy_Greedy
;
mHyphenationFrequency
=
kHyphenationFrequency_Normal
;
mLinePenalty
=
0.0
f
;
}
}
// namespace android
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录