Bug 153348

Summary: [Font Loading] Implement FontFaceSet
Product: WebKit Reporter: Myles C. Maxfield <mmaxfield>
Component: TextAssignee: Myles C. Maxfield <mmaxfield>
Status: RESOLVED FIXED    
Severity: Normal CC: cdumez, dino, fred.wang, jonlee, koivisto, mmaxfield, simon.fraser, thorton
Priority: P2    
Version: Other   
Hardware: Unspecified   
OS: Unspecified   
Bug Depends on:    
Bug Blocks: 153346, 153918, 158884    
Attachments:
Description Flags
Applied on top of attachment 270144
none
Applied on top of attachment 270144
none
Applied on top of attachment 270144
none
Applied on top of attachment 270144
none
Applied on top of attachment 270144
none
Applied on top of attachment 270478
none
WIP
none
WIP
none
Patch simon.fraser: review+

Myles C. Maxfield
Reported 2016-01-22 01:15:40 PST
Much of this implementation can perhaps be ported from the existing "FontLoader" class that's already in the tree.
Attachments
Applied on top of attachment 270144 (20.45 KB, patch)
2016-01-28 21:59 PST, Myles C. Maxfield
no flags
Applied on top of attachment 270144 (43.98 KB, patch)
2016-01-29 21:29 PST, Myles C. Maxfield
no flags
Applied on top of attachment 270144 (50.93 KB, patch)
2016-01-29 21:41 PST, Myles C. Maxfield
no flags
Applied on top of attachment 270144 (51.00 KB, patch)
2016-02-01 13:04 PST, Myles C. Maxfield
no flags
Applied on top of attachment 270144 (55.12 KB, patch)
2016-02-01 17:14 PST, Myles C. Maxfield
no flags
Applied on top of attachment 270478 (55.62 KB, patch)
2016-02-02 01:08 PST, Myles C. Maxfield
no flags
WIP (71.90 KB, patch)
2016-02-16 17:32 PST, Myles C. Maxfield
no flags
WIP (81.62 KB, patch)
2016-02-16 19:57 PST, Myles C. Maxfield
no flags
Patch (91.67 KB, patch)
2016-02-16 21:10 PST, Myles C. Maxfield
simon.fraser: review+
Myles C. Maxfield
Comment 1 2016-01-28 21:57:35 PST
*** Bug 153642 has been marked as a duplicate of this bug. ***
Myles C. Maxfield
Comment 2 2016-01-28 21:59:55 PST
Myles C. Maxfield
Comment 3 2016-01-29 21:29:34 PST
Myles C. Maxfield
Comment 4 2016-01-29 21:41:43 PST
Myles C. Maxfield
Comment 5 2016-02-01 13:04:59 PST
Myles C. Maxfield
Comment 6 2016-02-01 15:43:05 PST
We need to support iteration. Iteration must iterate in document-order, followed by non-CSS-connected fonts in insertion order.
Myles C. Maxfield
Comment 7 2016-02-01 15:44:00 PST
Adding a font that is CSS-Connected needs to throw a InvalidModificationError
Myles C. Maxfield
Comment 8 2016-02-01 15:46:04 PST
We need our loading/loaded status to match our constituent FontFaces. add() and remove() need to be updated to maintain this invariant.
Myles C. Maxfield
Comment 9 2016-02-01 15:47:55 PST
We need to implement event triggering.
Myles C. Maxfield
Comment 10 2016-02-01 17:14:22 PST
Myles C. Maxfield
Comment 11 2016-02-02 01:08:02 PST
Myles C. Maxfield
Comment 12 2016-02-16 17:32:30 PST
Myles C. Maxfield
Comment 13 2016-02-16 19:57:30 PST
Myles C. Maxfield
Comment 14 2016-02-16 21:10:05 PST
Myles C. Maxfield
Comment 15 2016-02-16 21:13:26 PST
Comment on attachment 271529 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=271529&action=review > LayoutTests/fast/text/font-face-set-javascript.html:24 > +var item = iterator.next(); I should test that fonts are iterated in insertion order.
Myles C. Maxfield
Comment 16 2016-02-17 10:09:02 PST
Comment on attachment 271529 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=271529&action=review > Source/WebCore/css/FontFaceSet.cpp:135 > + if (face.get().status() == CSSFontFace::Status::Failure) { This failure check should occur before we add anything to m_pendingPromises.
Simon Fraser (smfr)
Comment 17 2016-02-17 15:57:09 PST
Comment on attachment 271529 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=271529&action=review > Source/WebCore/css/CSSFontFace.h:2 > - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. > + * Copyright (C) 2016 Apple Inc. All rights reserved. You should preserve the 2007,2008 dates. > Source/WebCore/css/CSSFontFace.h:52 > + static Ref<CSSFontFace> create(CSSFontSelector& fontSelector, FontFace* wrapper = nullptr, bool isLocalFallback = false) { return adoptRef(*new CSSFontFace(fontSelector, wrapper, isLocalFallback)); } Should not all be on one line. > Source/WebCore/css/CSSFontFace.h:96 > + virtual void kick(CSSFontFace&) { }; Kick is not a very descriptive name. Please choose a new one. > Source/WebCore/css/CSSFontFaceSet.cpp:88 > + for (size_t i = 0; i < m_faces.size(); ++i) { Use a modern loop? > Source/WebCore/css/CSSFontFaceSet.cpp:97 > + ASSERT_NOT_REACHED(); Is it really impossible to hit this, even with bad JS? > Source/WebCore/css/CSSFontFaceSet.cpp:112 > +static bool familiesIntersect(CSSFontFace& face, const CSSValueList& request) const CSSFontFace& > Source/WebCore/css/CSSFontFaceSet.h:49 > + bool has(const CSSFontFace&) const; I would prefer hasFace() > Source/WebCore/css/CSSFontFaceSet.h:50 > + size_t size() const { return m_faces.size(); } Never really happy with size() as a count, since it's ambiguous with byte size. > Source/WebCore/css/CSSFontFaceSet.h:73 > + Status m_status { Status::Loaded }; Seems odd that the initial state is Loaded? > Source/WebCore/css/CSSSegmentedFontFace.cpp:58 > +void CSSSegmentedFontFace::kick(CSSFontFace&) Donut know what "kick" means. > Source/WebCore/css/FontFaceSet.h:57 > + bool has(FontFace*) const; > + size_t size() const; Ditto. > Source/WebCore/css/FontFaceSet.h:88 > + using RefCounted<FontFaceSet>::ref; > + using RefCounted<FontFaceSet>::deref; Why do you need these?
Chris Dumez
Comment 18 2016-02-17 16:12:43 PST
Comment on attachment 271529 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=271529&action=review > Source/WebCore/css/CSSFontFaceSet.cpp:119 > + for (auto &family1 : faceFamilies) { auto& > Source/WebCore/css/CSSFontFaceSet.cpp:165 > + for (auto face : matchingFaces) auto&? > Source/WebCore/css/CSSFontFaceSet.cpp:175 > + for (auto face : matchingFaces) { auto&? > Source/WebCore/css/CSSFontFaceSet.h:44 > +class CSSFontFaceSet : public CSSFontFace::Client { final? > Source/WebCore/css/FontFace.h:2 > + * Copyright (C) 2016 Apple Inc. All rights reserved. should keep the old dates. > Source/WebCore/css/FontFaceSet.cpp:123 > + if (!matchingFaces.size()) { matchingFaces.isEmpty() is a tad more readable. > Source/WebCore/css/FontFaceSet.cpp:128 > + for (auto face : matchingFaces) auto& > Source/WebCore/css/FontFaceSet.cpp:133 > + for (auto face : matchingFaces) { auto& > Source/WebCore/css/FontFaceSet.cpp:142 > + auto& vec = m_pendingPromises.add(RefPtr<FontFace>(face.get().wrapper()), Vector<Ref<PendingPromise>>()).iterator->value; vector > Source/WebCore/css/FontFaceSet.h:46 > +class FontFaceSet : public RefCounted<FontFaceSet>, public CSSFontFaceSetClient, public EventTargetWithInlineData, public ActiveDOMObject { final?
Myles C. Maxfield
Comment 19 2016-02-17 22:28:06 PST
Comment on attachment 271529 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=271529&action=review >> Source/WebCore/css/CSSFontFaceSet.cpp:88 >> + for (size_t i = 0; i < m_faces.size(); ++i) { > > Use a modern loop? I use "i" below. m_faces.remove(i); >> Source/WebCore/css/CSSFontFaceSet.cpp:97 >> + ASSERT_NOT_REACHED(); > > Is it really impossible to hit this, even with bad JS? Yes, FontFaceSet is an intermediary between JavaScript and this function, and it will only call this function if CSSFontFaceSet::has(). Like Darin says: "No aspirational ASSERT()s!" >> Source/WebCore/css/CSSFontFaceSet.cpp:165 >> + for (auto face : matchingFaces) > > auto&? Wow, my testing didn't catch this because "face" is a std::reference_wrapper :| >> Source/WebCore/css/CSSFontFaceSet.h:50 >> + size_t size() const { return m_faces.size(); } > > Never really happy with size() as a count, since it's ambiguous with byte size. I think it's more valuable to be consistent with C++ conventions rather than (weirdly) use Obj-C conventions. >> Source/WebCore/css/CSSFontFaceSet.h:73 >> + Status m_status { Status::Loaded }; > > Seems odd that the initial state is Loaded? The state is "loaded" iff there are 0 loads active. Otherwise, the state is "loading." >> Source/WebCore/css/FontFaceSet.h:88 >> + using RefCounted<FontFaceSet>::deref; > > Why do you need these? RefCounted has a ref() and deref() function, and EventTarget has a ref() and deref() function.
Myles C. Maxfield
Comment 20 2016-02-17 22:28:52 PST
Comment on attachment 271529 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=271529&action=review >>> Source/WebCore/css/CSSFontFaceSet.h:50 >>> + size_t size() const { return m_faces.size(); } >> >> Never really happy with size() as a count, since it's ambiguous with byte size. > > I think it's more valuable to be consistent with C++ conventions rather than (weirdly) use Obj-C conventions. What do you think I should name it?
Simon Fraser (smfr)
Comment 21 2016-02-17 22:39:07 PST
(In reply to comment #20) > Comment on attachment 271529 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=271529&action=review > > >>> Source/WebCore/css/CSSFontFaceSet.h:50 > >>> + size_t size() const { return m_faces.size(); } > >> > >> Never really happy with size() as a count, since it's ambiguous with byte size. > > > > I think it's more valuable to be consistent with C++ conventions rather than (weirdly) use Obj-C conventions. > > What do you think I should name it? faceCount? numberOfFaces()?
Myles C. Maxfield
Comment 22 2016-02-17 23:26:01 PST
Note You need to log in before you can comment on or make changes to this bug.