RESOLVED FIXED 206118
[GPU Process] Support drawing text in 2D canvas with font features
https://bugs.webkit.org/show_bug.cgi?id=206118
Summary [GPU Process] Support drawing text in 2D canvas with font features
Wenson Hsieh
Reported 2020-01-10 18:36:13 PST
E.g.: <style> @font-face { font-family: "SpecialFont"; src: url("resources/FontWithFeatures.ttf") format("truetype"); font-feature-settings: "titl" 1; } </style> … const context = document.querySelector("canvas").getContext("2d"); context.font = "80px SpecialFont"; context.fillText("bbb", 100, 100);
Attachments
WIP (37.09 KB, patch)
2020-01-10 19:48 PST, Wenson Hsieh
no flags
WIP (fix GTK/WPE) (38.81 KB, patch)
2020-01-10 22:30 PST, Wenson Hsieh
no flags
Adjust Win TestExpectations (40.32 KB, patch)
2020-01-11 14:43 PST, Wenson Hsieh
no flags
WIP (23.32 KB, patch)
2020-09-29 01:13 PDT, Myles C. Maxfield
no flags
Patch (24.00 KB, patch)
2020-09-29 22:11 PDT, Myles C. Maxfield
no flags
Patch (36.30 KB, patch)
2020-09-30 19:44 PDT, Myles C. Maxfield
no flags
Patch (37.71 KB, patch)
2020-10-01 14:15 PDT, Myles C. Maxfield
wenson_hsieh: review+
ews-feeder: commit-queue-
Patch for committing (42.02 KB, patch)
2020-10-01 17:25 PDT, Myles C. Maxfield
no flags
Patch for committing (40.08 KB, patch)
2020-10-01 17:29 PDT, Myles C. Maxfield
ews-feeder: commit-queue-
Patch for committing (40.48 KB, patch)
2020-10-02 11:02 PDT, Myles C. Maxfield
ews-feeder: commit-queue-
Patch for committing (40.75 KB, patch)
2020-10-02 15:35 PDT, Myles C. Maxfield
no flags
Radar WebKit Bug Importer
Comment 1 2020-01-10 18:48:14 PST
Wenson Hsieh
Comment 2 2020-01-10 19:48:02 PST Comment hidden (obsolete)
Wenson Hsieh
Comment 3 2020-01-10 22:30:04 PST Comment hidden (obsolete)
Wenson Hsieh
Comment 4 2020-01-11 14:43:32 PST
Created attachment 387447 [details] Adjust Win TestExpectations
Myles C. Maxfield
Comment 5 2020-01-17 19:27:18 PST
Comment on attachment 387447 [details] Adjust Win TestExpectations View in context: https://bugs.webkit.org/attachment.cgi?id=387447&action=review > Source/WebCore/ChangeLog:10 > + Augments and refactors some existing logic for propagating font information to the GPU process when painting > + glyphs using display lists, such that we preserve font feature settings. See below for more details. I'd appreciate a little explanation about why FontCreationParameters, Font, FontHandle (and possibly FontDescription) are different classes. What is the purpose each one needs to serve? > Source/WebCore/loader/cache/CachedFont.cpp:131 > + font->setFontCreationParameters({ *m_data, fontDescription, remoteURI, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceCapabilities }); Please consider putting all this data inside FontPlatformData instead of Font. That way this code wouldn't have to specify it twice. The existing code maintains the invariant that Font isn't allowed to have any members that aren't derivable from the FontPlatformData. So, if this stuff were retained inside the FontPlatformData, Font could just reach inside whenever it needs it. This seems like a fairly arbitrary place to pack/unpack a FontCreationParameters. I'd recommend either making FontCreationMembers a member field of FontPlatformData, or doing the packing/unpacking as late as possible inside code that knows about the GPU Process (and just packs the data as late as possible, just to send across the wire to the other process) > Source/WebCore/platform/graphics/Font.cpp:720 > + auto customFontData = CachedFont::createCustomFontData(parameters.data, { }, wrapping); > + font = Font::create(CachedFont::platformDataFromCustomData(*customFontData, parameters.description, parameters.syntheticBold, parameters.syntheticItalic, parameters.features, parameters.capabilities), Font::Origin::Remote); Is this code only used for web fonts? If so, can we move it closer to FontCustomPlatformData? If not, shouldn't serializing an installed font use the same infrastructure as serializing a web font? > Source/WebCore/platform/graphics/Font.h:222 > + bool hasFontCreationParameters() const { return m_fontCreationParameters.hasValue(); } Installed fonts need these creation parameters, too. Shouldn't all Fonts get these creation parameters? Why are they optional? > Source/WebKit/Shared/WebCoreArgumentCoders.cpp:1156 > + return FontHandle(); I don't understand. Under which situation would we receive a FontHandle but want it to be internally null? > Source/WebKit/Shared/WebCoreArgumentCoders.cpp:3143 > + decoder >> description; This just works??? What information from the FontDescription actually gets serialized?
Wenson Hsieh
Comment 6 2020-01-17 20:03:14 PST
Comment on attachment 387447 [details] Adjust Win TestExpectations View in context: https://bugs.webkit.org/attachment.cgi?id=387447&action=review >> Source/WebCore/ChangeLog:10 >> + glyphs using display lists, such that we preserve font feature settings. See below for more details. > > I'd appreciate a little explanation about why FontCreationParameters, Font, FontHandle (and possibly FontDescription) are different classes. What is the purpose each one needs to serve? Okay! I'll add some more words to the ChangeLog. Here's my take: - Font is the information used by (among other things) graphics code to paint glyphs. - FontHandle is a convenience wrapper for serializing and deserializing a Font (so if I have a Ref<Font> or RefPtr<Font>, it should be easy to serialize, e.g. over IPC). - As explained below, FontCreationParameters encapsulates the information needed to construct a Font (which mostly ends up being information needed to construct a FontPlatformData). >> Source/WebCore/loader/cache/CachedFont.cpp:131 >> + font->setFontCreationParameters({ *m_data, fontDescription, remoteURI, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceCapabilities }); > > Please consider putting all this data inside FontPlatformData instead of Font. That way this code wouldn't have to specify it twice. > > The existing code maintains the invariant that Font isn't allowed to have any members that aren't derivable from the FontPlatformData. So, if this stuff were retained inside the FontPlatformData, Font could just reach inside whenever it needs it. > > This seems like a fairly arbitrary place to pack/unpack a FontCreationParameters. I'd recommend either making FontCreationMembers a member field of FontPlatformData, or doing the packing/unpacking as late as possible inside code that knows about the GPU Process (and just packs the data as late as possible, just to send across the wire to the other process) Now that you pointed it out, it does seem like what I really wanted to serialize was the FontPlatformData itself. This would mean I wouldn't need a separate FontCreationParameters/FontCreationMembers class, and I think it would work for installed fonts too. I'll try this approach out and see, thanks! >> Source/WebCore/platform/graphics/Font.cpp:720 >> + font = Font::create(CachedFont::platformDataFromCustomData(*customFontData, parameters.description, parameters.syntheticBold, parameters.syntheticItalic, parameters.features, parameters.capabilities), Font::Origin::Remote); > > Is this code only used for web fonts? If so, can we move it closer to FontCustomPlatformData? If not, shouldn't serializing an installed font use the same infrastructure as serializing a web font? Yes, it's only for web fonts; I will move it over to FontCustomPlatformData. >> Source/WebCore/platform/graphics/Font.h:222 >> + bool hasFontCreationParameters() const { return m_fontCreationParameters.hasValue(); } > > Installed fonts need these creation parameters, too. Shouldn't all Fonts get these creation parameters? Why are they optional? Ok — I'll look into plumbing this information for installed fonts. For installed fonts, we currently just use the serialized platform font descriptor to send the information across, but it seems this is not enough. >> Source/WebKit/Shared/WebCoreArgumentCoders.cpp:1156 >> + return FontHandle(); > > I don't understand. Under which situation would we receive a FontHandle but want it to be internally null? FontHandle is an encodable wrapper around a nullable Font; that said, there's no situation currently where a FontHandle should contain a null font, so it's purely for convenience. The alternative would be defining functions like void encode(Encoder&, Font*) and Optional<RefPtr<Font>> decode(Decoder&). >> Source/WebKit/Shared/WebCoreArgumentCoders.cpp:3143 >> + decoder >> description; > > This just works??? What information from the FontDescription actually gets serialized? All of the information in FontDescription gets serialized.
Myles C. Maxfield
Comment 7 2020-09-29 01:13:38 PDT
Myles C. Maxfield
Comment 8 2020-09-29 01:18:21 PDT
This patch isn't quite sufficient. We need to add CreationParameters to the FontPlatformData in more places (e.g. CachedSVGFont).
Myles C. Maxfield
Comment 9 2020-09-29 22:09:44 PDT
(In reply to Myles C. Maxfield from comment #8) > This patch isn't quite sufficient. We need to add CreationParameters to the > FontPlatformData in more places (e.g. CachedSVGFont). Turns out it looks like all the calls get filtered through createFontCustomPlatformData(), which means it actually is sufficient.
Myles C. Maxfield
Comment 10 2020-09-29 22:11:41 PDT
Myles C. Maxfield
Comment 11 2020-09-30 19:44:59 PDT
Myles C. Maxfield
Comment 12 2020-10-01 14:15:50 PDT
Wenson Hsieh
Comment 13 2020-10-01 14:41:03 PDT
Comment on attachment 410269 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=410269&action=review > Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h:31 > + Nit - stray whitespace. > Source/WebKit/Shared/WebCoreArgumentCoders.cpp:1185 > + encoder << static_cast<uint8_t>(font->origin()); Nit - do we need all these static casts? IIRC for enums that have an explicit bit width, our Encoder/Decoders should know how to encode/decode them, so on the decoding side we can just have `Optional<Origin>`.
Myles C. Maxfield
Comment 14 2020-10-01 15:24:35 PDT
(In reply to Wenson Hsieh from comment #13) > Comment on attachment 410269 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=410269&action=review > > > Source/WebKit/Shared/WebCoreArgumentCoders.cpp:1185 > > + encoder << static_cast<uint8_t>(font->origin()); > > Nit - do we need all these static casts? IIRC for enums that have an > explicit bit width, our Encoder/Decoders should know how to encode/decode > them, so on the decoding side we can just have `Optional<Origin>`. I tried the naive thing, but it resulted in a compile error. You must be right, though - there's gotta be a way that does proper bounds checking on enums. I'll see if I can figure it out.
Myles C. Maxfield
Comment 15 2020-10-01 17:25:39 PDT
Created attachment 410287 [details] Patch for committing
Myles C. Maxfield
Comment 16 2020-10-01 17:29:10 PDT
Created attachment 410288 [details] Patch for committing
EWS
Comment 17 2020-10-01 18:16:09 PDT
Committed r267864: <https://trac.webkit.org/changeset/267864> All reviewed patches have been landed. Closing bug and clearing flags on attachment 410288 [details].
Aakash Jain
Comment 18 2020-10-02 05:23:16 PDT
(In reply to EWS from comment #17) > Committed r267864: <https://trac.webkit.org/changeset/267864> This commit added two broken tests: - fast/canvas/fill-text-with-font-variations.html broken on iOS and windows - fast/canvas/fill-text-with-font-features.html broken on windows EWS indicates similar failures on previous versions of patches on this bug. Should have waited for EWS to complete before marking cq+.
WebKit Commit Bot
Comment 19 2020-10-02 05:23:59 PDT
Re-opened since this is blocked by bug 217220
Myles C. Maxfield
Comment 20 2020-10-02 11:02:40 PDT
Created attachment 410339 [details] Patch for committing
Myles C. Maxfield
Comment 21 2020-10-02 15:35:29 PDT
Myles C. Maxfield
Comment 22 2020-10-02 15:35:50 PDT
Created attachment 410381 [details] Patch for committing
EWS
Comment 23 2020-10-03 10:31:35 PDT
Committed r267930: <https://trac.webkit.org/changeset/267930> All reviewed patches have been landed. Closing bug and clearing flags on attachment 410381 [details].
Myles C. Maxfield
Comment 24 2021-04-09 13:10:00 PDT
*** Bug 208878 has been marked as a duplicate of this bug. ***
Note You need to log in before you can comment on or make changes to this bug.