The hb_font_t object holds on to tables of font data, acquired through
the MinikinFont::GetTable interface, which is based on copying data
into caller-owned buffers. Now that we're caching lots of hb_font_t's,
the cost of these buffers is significant.
This patch moves to a different interface, inspired by HarfBuzz's
hb_reference_table API, where the font can provide a pointer to the
actual font data (which will often be mmap'ed, so it doesn't even
consume physical RAM).
Bug: 27860101
Change-Id: Id766ab16a8d342bf7322a90e076e801271d527d4
This patch eagerly purges the corresponding hb_font_t object from
the HbFontCache when the underlying MinikinFont is destroyed. After
that, the key will no longer be accessed, so having the entry is
wastes memory.
Bug: 27251075
Bug: 27860101
Change-Id: I1b98016133fe3baf6525ac37d970a65ddccadb4f
With this CL, measureText is used for getRunAdvance,
getOffsetForAdvance and line breaking.
Bug: 24505153
Change-Id: Ib699f6b1391b46537736fc274cdb41686586b550
Recent changes have added special cases for line breaks within URLs
and email addresses. Such breaks are undesirable when they can be
avoided, but at other times are needed to avoid huge gaps, or indeed
to make the line fit at all.
This patch assigns a penalty for such breaks, equal to the hyphenation
penalty. The mechanism is currently very simple, but would be easy to
fine-tune based on more detailed information about break quality.
Bug: 20126487
Bug: 20566159
Change-Id: I0d3323897737a2850f1e734fa17b96b065eabd9c
This change adds accceptable line breaks according to sections 7.42
(Dividing URLs and e-mail addresses) and 14.12 (URLs or DOIs and line
breaks) of the Chicago Manual of Style (16th ed.). In general, these
place breaks before punctuation symbols, and suppresses them after
hyphens.
Bug: 20126487
Bug: 20566159
Change-Id: I2d07d516b920a506a2f718c38fb435c5eb1ee1f8
Detect URLs and email addresses, and suppress both line breaking and
hyphenation within them.
Bug: 20126487
Bug: 20566159
Change-Id: I43629347a063dcf579e355e5b678d7195f453ad9
Before this patch, the font fallback chain iterated all installed font
families if a variation selector was specified.
This CL narrows down the range of iteration.
To decide the font family for the variation sequence, we need to search
for both the variation sequence and its base code point.
The new range of the iteration is a union of them.
With this change, the running time of Paint.hasGlyph for the variation
sequence improves 50% and the running time of Paint.measureText for the
variation sequence improves 40% for the large text case on Nexus 6
userdebug.
Bug: 26784699
Bug: 11750374
Change-Id: Iced1349e3ca750821d8882c551551f65bb569794
Implement a WordBreaker that defines our concept of valid word
boundaries, customizing the ICU behavior. Currently, we suppress line
breaks at soft hyphens (these are handled specially). Also, the
new WordBreaker class has methods that determine the start and end
of the word (punctuation stripped) for the purpose of hyphenation.
This patch, in its current form, doesn't handle email addresses and
URLs specially, but the WordBreaker class is the correct place to do
so. Also, special case handling of hyphens and dashes is still done
in LineBreaker, but all of that should be moved to WordBreaker.
Bug: 20126487
Bug: 20566159
Change-Id: I492cbad963f9b74a2915f010dad46bb91f97b2fe
It turned out that hb_font_t creation is not a lightweight operation.
Especially, Paint.hasGlyph creates hb_font_t for all existing fonts
every time. To improve the performance, cache hb_font_t instead
of hb_face_t.
Note that to calculate horizontal advance, MinikinPaint needs to be
associated with hb_font_t by calling hb_font_set_funcs. With this patch,
hb_font_set_funcs may be called multiple times for the same hb_font_t
object. However this is not an issue since MinikinPaint is unique
during layout.
Bug: 26784699
Change-Id: I516498ae9f0127d700fc9829327e9789845a1416
The intruduced method measureText can be used instead of
doLayout for text measurement purpose.
Bug: 24505153
Change-Id: Ic29bbb347daf18d1f6c13f86970dcdd11dd6a2bd
The motivation of this CL is enhance the font fallback score design
to support multiple language font fallback.
This CL contains following changes:
- Break language based font score into two: script-based score and
primary-language-based score.
- The primary-language-based score is 0 if the script-based score is 0.
If the script-based score is not 0 and the primary language is the
as same as the requested one, the font gets an extra score of 1.
- The language score gets a higher multiplier for languages higher in
the locale list.
Bug: 25122318
Bug: 26168983
Change-Id: Ib999997a88e6977e341f4c325e2a1b41a59db2d5
This is 2nd attempt of I8df992a6851021903478972601a9a5c9424b100c.
The main purpose of this CL is expanding FontLanguage to be able to
save full script tag. Previously, FontLangauge kept only limited script
tags. With this CL, FontLanguage keeps all script tags.
This CL contains the following changes:
- FontLanguage changes:
-- Moved to private directory not to be instantiated outside of Minikin.
-- Removed bool(), bits(), FontLanguage(uint32_t) methods which are no
longer used.
-- Change the FontLanguage internal data structure.
-- Introduces script match logic.
- FontLanguages changes:
-- Moved to private directory not to be instantiated outside of Minikin.
-- This is now std::vector<FontLanguage>
- FontLanguageListCache changes:
-- Now FontLanguageListCache::getId through
FontStyle::registerLanguageList is the only way to instantiate the
FontLanguage.
-- Normalize input to be BCP47 compliant identifier by ICU.
Bug: 26168983
Change-Id: I431b3f361a7635497c05b85e8ecbeb48d9aef63e
The main purpose of this CL is expanding FontLanguage to be able to
save full script tag. Previously, FontLangauge kept only limited script
tags. With this CL, FontLanguage keeps all script tags.
This CL contains the following changes:
- FontLanguage changes:
-- Moved to private directory not to be instantiated outside of Minikin.
-- Removed bool(), bits(), FontLanguage(uint32_t) methods which are no
longer used.
-- Change the FontLanguage internal data structure.
-- Introduces script match logic.
- FontLanguages changes:
-- Moved to private directory not to be instantiated outside of Minikin.
-- This is now std::vector<FontLanguage>
- FontLanguageListCache changes:
-- Now FontLanguageListCache::getId through
FontStyle::registerLanguageList is the only way to instantiate the
FontLanguage.
-- Normalize input to be BCP47 compliant identifier by ICU.
Bug: 26168983
Change-Id: I8df992a6851021903478972601a9a5c9424b100c
Removing the extra score of 2 for the script matching from the font
fallback score calculation. If the two langauges have different
scripts, we should treat them as different languages.
Change-Id: Ie0d6f27bd1086248895935a7bd01b5d404044ad0
FontLanguageListCache is an intentionally leaky singleton and its
internal cache won't be purged.
BUG: 25122318
Change-Id: I272097e979fe44b83fd86822235350e12eda8f51
If U+FE0E is appended to the emoji code point, the glyph should have a
text presentation.
On the other hand, if U+FE0F is appended to the emoji code point, the
glyph should have an emoji presentation.
Bug: 11256006
Change-Id: I5187d44500b13a138e7ffbcf2c72e2da06374c8c
To implement Paint.hasGlyph(), we need a new method to ask the
FontCollection if it has a glyph for the code point and variation
selector pair.
Bug: 11256006
Change-Id: Ie4185c91bcaa4d01aee6beb97784b1f9d2a88f12
This is 2nd trial of I30a0914a4633bd93eb60957cdf378770f04d8428
- To suppress noisy unused parameter warnings, comment out unused
arguments.
- Add -Werror for suppressing further warning.
- Add -Wall -Wextra for safety.
- Use "z" prefix for format string of size_t.
Verified that compile succeeded on all arm,arm64,mips,x86,x86_64.
Change-Id: I7ad208464486b8a35da53929cb1cfe541ed0052f
The behavior hasn't changed much yet: all languages are ignored for
rendering text, except the very first supported language.
Change-Id: I1695fb985927ae5e28e4f59c1b531e4993af8688
This CL contains the following changes:
- Add a variation selector argument into getFamilyForChar to be able to
select fonts which support variation selector.
- In case no fonts support the codepoint and variation selector pair,
add a fallback rule which selects font family with ignoring variation
selector.
- Change FontCollection::itemize to not change the font family
immediately preceding a variation selector.
- Introduce unit tests for variation selectors.
With this CL, TextView can render the variation selectors correctly.
Bug: 11256006
Change-Id: I22ce0e9eadc941f84e3a9b23462f194e51dd7180
This CL introduces new method hasVariationSelector into FontFamily but it
is not used in production code. So no behavior changes are expected.
This CL contains the following changes:
- Introduce hasVariationSelector which returns true if the corresponding
font has a glyph for a code point and variation selector pair.
- Introduce purgeHbFontCache since hb_face_t won't be released by
keeping hb_font_t.
- Introduce unit tests with self-built font.
Change-Id: I659a6d03d9ec446b409e1fba2758452abb9f44fa
In the current state, hyphenation in all languages than Sanskrit seems
to work (case-folding edge cases). Thus, we just disable Sanskrit.
Packed tries are implemented, but not the finite state machine
(space/speed tradeoff).
This commit contains a throw-away test app, which runs on the host.
I think I want to replace it with unit tests, but I'm including it in
the CL because it's useful during development.
Bug: 21562869
Bug: 21826930
Bug: 23317038
Bug: 23317904
Change-Id: I7479a565a4a062fa319651c2c14c0fa18c5ceaea
Also handle the case of weird language code that we don't understand
properly better, by treating them not equal to each other.
Change-Id: Iaccb251fa38d700932f6eadac254d3d1fa09b3ea
We bypass the word layout cache for "complex" cases, which includes
things like OpenType features. We were counting a hyphen edit as such
a case, but the problem is that we measure a _lot_ of these when
doing layout with hyphenation.
This patch adds plumbing for hyphen edits to the layout cache, so
that word fragments with hyphens can be cached as well.
Bug: 22378829
Change-Id: Idba4df4faa14f48a5faccc8a7a7955a36c19ef27
Tuning for hyphenation parameters. We discourage hyphenation on the
last line, but offset this penalty by also applying a penalty for
each line, which optimizes for minimizing the number of lines. Thus,
when hyphenation can reduce the number of lines, it increases the
chance they're used.
There's probably more tuning and refinement that can be done, but
testing suggests that the tunable parameters are appropriate.
Bug: 20883322
Change-Id: Ida7eaf8aced109e426694f5a386924a842d29c4b
Three hyphenation frequencies are now supported:
kHyphenationFrequency_None, which turns off both automatic
hyphenation and soft hyphens.
kHyphenationFrequency_Normal, which has aconservative amount of
hyphenation useful as a conservative default.
kHyphenationFrequency_Full, which has a typographic-quality amount of
hyphenation useful for running text and tight screens.
Bug: 21038249
Change-Id: I2800f718c887c9389a1a059d7ec07d7fa2ca1dee
New functions for computing the correspondence between cursor
position and advance, respecting grapheme boundaries.
Change-Id: I620378d5f64cd74300cd43db522adeb555825dff
The name "margin" conflicts with another meaning, so we're making the
name in the public api "idents" and the code consistent in naming.
Change-Id: I9170116b4d972e4b25f0f319e78376310288eb41
In order to support layout in non-rectangular regions, the LineWidths
object needs to accept an arbitrary array of margins. This is
implemented in addition to the existing firstWidthLineCount/restWidth
mechanism for convenience, though using only arrays would have the
same expressive power.
Bug: 20182243
Change-Id: Iea96bca1a92012314ac27e617c67f306c1f1b2f2
This patch adds hyphenation using the Liang hyphenation algorithm,
similar to TeX. It also improves the optimized line breaker so that
it works correctly and efficiently even when the line width is not
constant (there is a specialization for constant width, which is
probably worthwhile, but performance TODOs remain).
Still to be done:
* hyphenator has many shortcuts, only tested with English
* interaction between punctuation and hyphenation is problematic
Change-Id: I2d94a1668ebc536398b7c43fcf486333eeb7c6aa
This patch adds a LineBreaker class to Minikin, which will be used for
computing line breaks in StaticLayout. The version in this patch
contains basically the same functionality that existed before, but
hopefully better performance and an interface that's suitable for more
sophisticated paragraph layout.
Note that this version contains a high quality strategy, which mostly
works but doesn't respect varying line width.
Change-Id: I02485d58b1e52856296a72cdd4efd963bc572933
Adds a "HyphenEdit" field to the Minikin Paint object, which represents
an edit to the text to add a hyphen (and, in the future, other edits to
support nonstandard hyphenation).
Change-Id: Ib4ee690b0fe2137e1d1e2c9251e5526b274ec3a7
For build-system CFLAGS clean-up, fix unused variables.
Reorder initializer list to initialize in the order of member
declarations.
Change-Id: I64358b2dcf0e39d0f4e18fdc3473de867f84fcba
This will significantly reduce memory usage and also speed the creation
of new font families. In particular, the coverage bitmaps for the fonts
in the fallback stack will be computed once in the Zygote, rather than
separately in each app process.
Bug: 17756900
Change-Id: I66f5706bddd4658d78fe5b709f7251ca9d2ff4f8
Fractional advance widths were causing subtle problems with text
positioning when the same text was drawn with different spans in the
hwui renderer. Quantizing the coordinates on layout (as opposed to
waiting until the renderer draws the glyphs) solves the problem.
This patch also fixes a discrepancy between x position and advance
widths when letterspacing.
Bug: 17347779
Change-Id: Ia705944047408c2839d5ad078eefd6bbec446872
C++ local var initialization always tricks me. Previously, Layout
didn't have a constructor, which meant that defining it on the stack
left mAdvance uninitialized. This was not an issue when we were doing
"new Layout()", since that invokes zero-initialization, but was an
issue for the skipCache path that was allocating layout on stack by
just "Layout l" instead of "Layout l = Layout()". To avoid surprises,
add a constructors that clears everything.
Also adds reset() method to reset the layout for reuse.
Change-Id: I3e02f00da9dd7d360abe13f63c310f6882292d0a