Clear baseLayoutStyle when the font selector version has increased.

FontFaceCache has a version() member which is increased when we add fonts
to the cache. It is used to detect if new fonts have been added to the
cache after a LayoutStyle was calculated. Different version() numbers will
make Font comparison fail and trigger relayout with new font data.

When the font added to the cache is new to the style system, it is
accompanied by a full document recalc. If we add a stylesheet with an
@font-face rule, the @font-face will cause an addition to the font cache,
and a document style recalc. So, if we have a "font-family:webfont,serif"
where "webfont" does not match anything, we lay out with the serif "font".
If we then add a stylesheet with an @font-face for "webfont", we need to
re-layout with that new font even if the computed style for font-family
doesn't change. That is triggered by the version number incremented by the
addition of "webfont".

This is all well until we add or remove a stylesheet which causes an
analyzed stylesheet update where we get a Reconstruct. The StyleResolver
will be recreated and font faces will be re-added, hence increasing the
version number of the font cache. The analyzed stylesheet update is smart
enough to avoid a full document recalc if it figures out that we did not
really add or remove any @font-face rules, just re-adding the ones we had.

We will then end up with a computed Font that was created for a different
font cache version, but we figured out we didn't need to recompute the
style or relayout since the font cache didn't really change with the
increased version.

If we are animating an element while such a reconstruct happen, we end up
having a baseLayoutStyle for the animation which is based on an old font
cache version. The LayoutStyle comparison ASSERT for baseLayoutStyle in
ElementAnimations will trigger because the Font comparison will fail,
since the version number for a newly created LayoutStyle Font will be
different.

To avoid that, we throw away the baseLayoutStyle after such a reconstruct
happens, in which case the stored version in the FontFallbackList will not
be in sync with the one stored in the FontFaceCache.

The real bug here is that the version tagging/increment here is imprecise
and not correlated with needsStyleRecalc. Removing an empty stylesheet
like in the added test-case will cause any element to be re-layout the
next time some other computed style change happen on that element as we
detect that the version number is out of sync. I have reported
crbug.com/471079 for that.

There is a generation() in FontCache which is similar to version(), but
increasing that will always trigger a full document recalc in
StyleEngine::fontsNeedUpdate.

R=esprehn@chromium.org,dstockwell@chromium.org,eae@chromium.org
BUG=470458

Review URL: https://codereview.chromium.org/1038193002

git-svn-id: svn://svn.chromium.org/blink/trunk@192669 bbb929c8-8fbe-4397-9dbb-9b2b20218538
8 files changed
tree: ee8c29146d6bf47a1b5b44ac07f91e5d064a244e
  1. third_party/