Title: [281389] trunk
Revision
281389
Author
mmaxfi...@apple.com
Date
2021-08-21 22:41:27 -0700 (Sat, 21 Aug 2021)

Log Message

overwriteCodePoint() in createAndFillGlyphPage() is wrong
https://bugs.webkit.org/show_bug.cgi?id=215643
<rdar://problem/67430461>

Reviewed by Alan Bujtas.

Source/WebCore:

The CSS spec says that certain characters have to be invisible. Previously, we were doing this
by just treating these characters as if they were the zero width space character. However, this
is wrong for 2 reasons:

1. If the primary font supports the desired character but doesn't support the zero width space
       character, we'll fallback past it and trigger a download for secondary fonts until
       we find one that supports the ZWS character (which the page didn't even ask for!)
2. Shaping is Turing-complete, and expects that the correct glyphIDs are fed into the shaper.
       We can't just arbitrarily swap out glyphIDs before shaping just because we feel like it.

Instead, the solution is to handle these invisible characters after font fallback, and after
shaping. This patch does it just like we handle adding letter-spacing, word-spacing, and
justification after shaping - by iterating over the glyphs output by the shaper and seeing if
any need to be adjusted.

This patch also includes a fix for the situation where the glyph buffer might be left in an
inconsistent state, where the array of glyphs is shorter than the array of characters -
this new codepath added in this patch revealed this existing problem, and fixes it here too.

Test: fast/text/zwj-ligature.html

* platform/graphics/Font.cpp:
(WebCore::createAndFillGlyphPage):
(WebCore::overrideControlCharacters): Deleted.
* platform/graphics/GlyphBuffer.h:
(WebCore::GlyphBuffer::glyphAt const):
(WebCore::GlyphBuffer::deleteGlyphWithoutAffectingSize):
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::applyCSSVisibilityRules):
(WebCore::WidthIterator::advance):
* platform/graphics/WidthIterator.h:

Source/WTF:

* wtf/unicode/CharacterNames.h:

LayoutTests:

* fast/text/resources/Ahem-GSUB-ligatures.ttf: Added.
* fast/text/zwj-ligature-expected.html: Added.
* fast/text/zwj-ligature.html: Added.
* platform/mac/fast/text/format-control-expected.txt: Progression! A new ligature is formed that wasn't formed before.
      Also, this ligature is formed in both Chrome and Firefox, so we match them now.
* platform/win/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (281388 => 281389)


--- trunk/LayoutTests/ChangeLog	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/LayoutTests/ChangeLog	2021-08-22 05:41:27 UTC (rev 281389)
@@ -1,3 +1,18 @@
+2021-08-21  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        overwriteCodePoint() in createAndFillGlyphPage() is wrong
+        https://bugs.webkit.org/show_bug.cgi?id=215643
+        <rdar://problem/67430461>
+
+        Reviewed by Alan Bujtas.
+
+        * fast/text/resources/Ahem-GSUB-ligatures.ttf: Added.
+        * fast/text/zwj-ligature-expected.html: Added.
+        * fast/text/zwj-ligature.html: Added.
+        * platform/mac/fast/text/format-control-expected.txt: Progression! A new ligature is formed that wasn't formed before.
+              Also, this ligature is formed in both Chrome and Firefox, so we match them now.
+        * platform/win/TestExpectations:
+
 2021-08-21  Alan Bujtas  <za...@apple.com>
 
         [LFC][IFC] Add support for -webkit-text-security: disc

Added: trunk/LayoutTests/fast/text/resources/Ahem-GSUB-ligatures.ttf (0 => 281389)


--- trunk/LayoutTests/fast/text/resources/Ahem-GSUB-ligatures.ttf	                        (rev 0)
+++ trunk/LayoutTests/fast/text/resources/Ahem-GSUB-ligatures.ttf	2021-08-22 05:41:27 UTC (rev 281389)
@@ -0,0 +1,47 @@
+\x80@GSUB\xB2\xA2\xB4\xA0\xCC^OS/2sf\xF8,`cmap9\x96U\xEE\x8Cgasp	\x98glyf0*	\xFD\xA8\xA8head\xDBP͵!P6hhea
+7!\x88$hmtx+!\xACXloca\xBEԸ7&.maxp	(4 nameM\xDAc(T1\xAEpostc\xA1[#Z
+,DFLTliga
+#$
+R$R\xD6\x90\xBC\x8A\x8F\xBC\x8A\xC52\x80\xAF HW3C @ \xFE\xFF \xFF8 \xC8\xFF\xFC\xFF\xFF   \xF8::&~\xA0\xA1\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC5\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCF\xD0\xD1\xD2\xD4\xD5\xD6\xD7\xD8\xD9\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEB\xEC\xED\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFC\xFD\xFE\xFF1Sx\x92\xC6\xC7\xC9\xDA\xDB\xDC\xDD\x94\xA5\xA7\xA9\xBC\xC0   +      " & 0 : D!"!&"""""""""+"H"
 ;`"e"\xF2%\xCA00NNN	N]N\x8CN\x94QkQmSAV\xD7V\xDBWg(j*l4pk~\xB5\x91\xD1\xF0\xFE\xFF\xFF\xFF (\xA0\xA1\xA2\xA4\xA5\xA6\xA7\xA8\xA9
 \xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC6\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xD0\xD1\xD2\xD3\xD5\xD6\xD7\xD8\xD9\xDA\xDC\xDD\xDE\xDF\xE0\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xEC\xED\xEE\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFD\xFE\xFF1Rx\x92\xC6\xC7\xC9\xD8\xDB\xDC\xDD\x94\xA5\xA7\xA9\xBC\xC0  	         & 0 9 D!"!&"""""""""+"H"`"d"\xF2%\xCA00NNN	N]N\x8CN\x94QkQmSAV\xD7V\xDBWg(j*l4pk~\xB5\x91\xD1\xF0\xFE\xFF\xFF\xFF\xFF\xE3\xFF\xE2\xFF\xF9\xFF\xF4\xFF\xE0\xFF\xFD\xFF\xE9\xFF\xDD\xFF\xE2\xFF\xDF\xFF\xE6\xFF\xEC\xFF\xEA\xFF\xD9\xFF\xD1\xFF\xDC\xFF\xD5\xFF\xDA\xFF\xCF\xFF\xEB+\xFF\xD7\xFF\xDD+\xFF\xD5\xFF\xDA\xFF\xE4\xFF\xE
 1\xFF\xD8\xFF\x9D\xFF\xC5\xFF\x9C\xFF\xDF\xFF\x9B\xFF\xDA\xFF\xDB\xFF\xDF\xFF\xDB\xFF\
 xEE\xFF\x94\xFF\xDC\xFF\xD9\xFF\xC7\xFF\x90\xFF\xEE\xFF\xB4\xFF\xD8\xFF\xD5\xFF\x8B\xFF\xE3\xFF\xE4\xFF\xA7\xFF\x89\xFF\x87\xFF\x88\xFF\x89\xFF\x87\xFF\x88\xFF\xAC\xFF\x87\xFF\x88\xFF\x86\xFF\x87\xFF\x88\xFF\x86\xFF\x87\xFF\xCF\xFF\x86\xFF\x87\xFF\x85\xFF\x86\xFF\x87\xFF\x85\xFF\xA8\xFF\x9B\xFF\x85\xFF\x83\xFF\x84\xFF\xC4\xFF\xC5\xFF\xA1\xFF\x81\xFF|\xFFX\xFF?\xFD\xED\xFD\xF5\xFD\xEC\xFD\xDE\xFD\xE0\xFD\xD8\xFD\xDD\xFD>\xFDo\xFDk\xFD*\xFC\xD3\xFD\xE0\xF4\xE0\xF2\xE0\xF3\xDF\xFF\xE0\xC2\xE0\x85\xE0\xBD\xE0\xBC\xE0\xBB\xE0\xB8\xE0\xAF\xE0\xA7\xE0\x9E\xDF\xC1߭\xDE\xE2\xDE\xCC\xDE\xD6\xDE\xD5޲މ\xDE\xCD\xDE\xCA޾ޥފއ\xDD\xFB\xDB$\xD0\xFE\xD1\xB3\xB3\xB2\xFA\xB2\xAC\xB2v\xB2q\xAF\x9D\xAF\x99\xADɪ5\xAA)\xA9\xF2\x99\xE7\x96\xE9\x94ڐ\xA2\x82`o?\xEF\xF6
 
 \xFF\xFF}k 3!%!!}\xEE\xFD\x8F\xF4\xFE \xFC\xE0}&\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8
 \xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC
 \xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8
 \xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8
  !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !
 !\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE
 8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE81!!\xE8\xFC\xC8\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \
 xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC
 \xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xE8 !!\xE8\xFC \xFC\xE0\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF
 8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8
  !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !
 !\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE
 8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \x
 FC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC
 \xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xF
 F8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE
 8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 
 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\
 xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC 
 \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xF
 C\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\xFF8\xE8 !!\xE8\xFC \xFC\x90\xE8X!!\xE8\xFCX\xC8\x90\xE8X!!\xE8\xFCX\xC8\xC8\xFF8\x90 3#\xC8\xC8\xC8 \xFC
 \xC8\xFF8\x90 3#\xC8\xC8\xC8 \xFC\x80\xFD\x89\x92\xBC_<\xF5	\xE8\xB3o_Y\xC4ݫ$\xFF8\xE8 
  \xFF8\xE8\xE8\xE8}\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8
 \xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8
 \xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8
 \xF4\xE8M\xFA\xA7\xC8d\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xE8\xC8\xE8\xC8
 !.;HUbo|\x89\x96\xA3\xB0\xBD\xCA\xD7\xE4\xF1\xFE%2?LYfs\x80\x8D\x9A\xA7\xB4\xC1\xCE\xDB\xE8\xF5)6CP]jw\x84\x91\x9E\xAB\xB8\xC5\xD2\xDF\xEC\xF9 -:GTan{\x88\x95\xA2\xAF\xBC\xC9\xD6\xE3\xF0\xFD
+#0=JWdq~\x8B\x98\xA5\xB2\xBF\xCC\xD9\xE6\xF3+'4AN[hu\x82\x8F\x9C\xA9\xB6\xC3\xD0\xDD\xEA\xF7+8ER_ly\x86\x93\xA0\xAD\xBA\xC7\xD4\xE1\xEE\xFB"/<IVcp}\x8A\x97\xA4\xA4\xB1\xBE\xCB\xD8\xE5\xF2\xFF&3@MZgt\x81\x8E\x9B\xA8\xB5\xC2\xCF\xDC\xE9\xF6				*	7	D	Q	^	k	x	\x85	\x92	\x9F	\xAC	\xB9	\xC6	\xD3	\xE0	\xED	\xFA
+
+
+!
+.
+;
+H
+U
+b
+o
+|
+\x89
+\x96
+\xA3
+\xB0
+\xBD
+\xCA
+\xD7
+\xE4
+\xF1
+\xFE%2?LYfs\x80\x8D\x9A\xA7\xB4\xC1\xCE\xDB\xE8\xF5)6CCCCCCCCCCCCCP]jw\x84\x91\x9E\xAB\xB8\xC5\xD2\xDF\xEC\xF9+++ +-+:+G+T$\xB6\xF0\xF0\xF8"(0H
+XP$\xA8R\xCC\xF8!26B
+,Fr)\x84\xAD\xB1\xB8	\xF0\xBC	\xAC	\xB4	"\xC2	\xE4	\xEC		
+X	$/d	R/\x88	/\xDA	/\xE2	/\xF0The Ahem font belongs to the public domain. In jurisdictions that do not recognize public domain ownership of these files, the following Creative Commons Zero declaration applies: http://labs.creativecommons.org/licenses/zero-waive/1.0/us/legalcodeAhemRegularVersion 1.50 AhemAhemVersion 1.50AhemThe 
 Ahem font was developed by Todd Fahrner and Myles C. Maxfield to help test writers develop predictable tests. The units per em is 1000, the advance is 800, and 
 the descent is 200, thereby making the em square exactly square. The glyphs for most characters is simply a box which fills this square. The codepoints mapped to this full square with a full advance are the following ranges: U+20-U+26, U+28-U+6F, U+71-U+7E, U+A0-U+C8, U+CA-U+FF, U+131, U+152-U+153, U+178, U+192, U+2C6-U+2C7, U+2C9,
  U+2D8-U+2DD, U+394, U+3A5, U+3A7, U+3A9, U+3BC, U+3C0, U+2013-U+2014, U+2018-U+201A, U+201C-U+201E, U+2020-U+2022, U+2026, U+2030, U+2039-U+203A, U+2044, U+2122, U+2
 126, U+2202, U+2206, U+220F, U+2211-U+2212, U+2219-U+221A, U+221E, U+222B, U+2248, U+2260, U+2264-U+2265, U+22F2, U+25CA, U+3007, U+4E00, U+4E03, U+4E09, U+4E5D, U+4E8C, U+4E94, U+516B, U+516D, U+5341, U+56D7, U+56DB, U+571F, U+6728, U+6C34, U+706B, U+91D1, U+F000-U+F002. The codepoints which are mapped to something else are the f
 ollowing: " " (U+20): No path but full advance; "p" (U+70): Path has 0 ascent but full descent; "\xC9" (U+C9): Path has 0 descent but full ascent; Non-br
 eaking space (U+A0): No path but full advance; Zero-width non-breaking space (U+FEFF): No path and 0 advance; En space (U+2002): No path and half advance; Em space (U+2003): No path but full advance; Three-per-em space (U+2004): No path and one third advance; Four-per-em space (U+2005): No path and one quarter advance; Six-per-em 
 space (U+2006): No path and one sixth advance; Thin space (U+2009): No path and one fifth advance; Hair space (U+200A): No path and one tenth advance; Zero width spac
 e (U+200B): No path and no advance; Ideographic space (U+3000): No path but full advance; Zero width non-joiner (U+200C): No path and no advance; Zero width joiner (U+200D): No path and no advance; Greek capital letter Chi (U+3A7): Thin horizontal stripe and full advance; (U+6A2A): Thin horizontal stripe and full advance; Greek cap
 ital letter Upsilon (U+3A5): Thin vertical stripe and full advance; (U+7EB5): Thin vertical stripe and full advance.http://www.w3c.orghttp://dev.w3.org/CSS/fonts/ahem
 /COPYING
+The Ahem font belongs to the public domain. In jurisdictions that do not recognize public domain ownership of these files, the following Creative Commons Zero declaration applies: http://labs.creativecommons.org/licenses/zero-waive/1.0/us/legalcodeAhemRegularVersion 1.50 AhemAhemVersion 1.50AhemThe Ahem font was developed by Todd Fahrner and Myles C. Maxfield to help test writers develop predictable tests. The units per em is 1000, the advance is 800, and the descent is 200, thereby making the em square exactly square. The glyphs for most characters is simply a box which fills this square. The codepoints mapped to this full square with a full advance are the following ranges: U+20-U+26, U+28-U+6F, U+71-U+7E, U+A0-U+C8, U+CA-U+FF, U+131, U+152-U+153, U+178, U+192, U+2C6-U+2C7, U+2C9, U+2D8-U+2DD, U+394, U+3A5, U+3A7, U+3A9, U+3BC, U+3C0, U+2013-U+2014, U+2018-U+201A, U+201C-U+201E, U+2020-U+2022, U+2026, U+2030, U+2039-U+203A, U+2044, U+2122, U+2126, U+2202, U+2206, U+220F, U+2211-U+
 2212, U+2219-U+221A, U+221E, U+222B, U+2248, U+2260, U+2264-U+2265, U+22F2, U+25CA, U+3007, U+4E00, U+4E03, U+4E09, U+4E5D, U+4E8C, U+4E94, U+516B, U+516D, U+5341, U+56D7, U+56DB, U+571F, U+6728, U+6C34, U+706B, U+91D1, U+F000-U+F002. The codepoints which are mapped to something else are the following: " " (U+20): No path but full advance; "p" (U+70): Path has 0 ascent but full descent; "\x83" (U+C9): Path has 0 descent but full ascent; Non-breaking space (U+A0): No path but full advance; Zero-width non-breaking space (U+FEFF): No path and 0 advance; En space (U+2002): No path and half advance; Em space (U+2003): No path but full advance; Three-per-em space (U+2004): No path and one third advance; Four-per-em space (U+2005): No path and one quarter advance; Six-per-em space (U+2006): No path and one sixth advance; Thin space (U+2009): No path and one fifth advance; Hair space (U+200A): No path and one tenth advance; Zero width space (U+200B): No path an
 d no advance; Ideographic space (U+3000): No path but full advance; Zero width non-joiner (U+200C): No path and no advance; Zero width joiner (U+200D): No path and no advance; Greek capital letter Chi (U+3A7): Thin horizontal stripe and full advance; (U+6A2A): Thin horizontal stripe and full advance; Greek capital letter Upsilon (U+3A5): Thin vertical stripe and full advance; (U+7EB5): Thin vertical stripe and full advance.http://www.w3c.orghttp://dev.w3.org/CSS/fonts/ahem/COPYING
+AhemRegularAhemThe Ahem font belongs to the public domain. In jurisdictions that do not recognize public domain ownership of these files, the following Creative Commons Zero declaration applies: http://labs.creativecommons.org/licenses/zero-waive/1.0/us/legalcodeAhemRegularVersion 1.50 AhemAhemVersion 1.50AhemThe Ahem font was developed by 
 Todd Fahrner and Myles C. Maxfield to help test writers develop predictable tests. The units per em is 1000, the advance is 800, and the descent is 200, thereby mak
 ing the em square exactly square. The glyphs for most characters is simply a box which fills this square. The codepoints mapped to this full square with a full advance are the following ranges: U+20-U+26, U+28-U+6F, U+71-U+7E, U+A0-U+C8, U+CA-U+FF, U+131, U+152-U+153, U+178, U+192, U+2C6-U+2C7, U+2C9, U+2D8-U+2DD, U+394, U+3A5, U+
 3A7, U+3A9, U+3BC, U+3C0, U+2013-U+2014, U+2018-U+201A, U+201C-U+201E, U+2020-U+2022, U+2026, U+2030, U+2039-U+203A, U+2044, U+2122, U+2126, U+2202, U+2206, U+220F, U
 +2211-U+2212, U+2219-U+221A, U+221E, U+222B, U+2248, U+2260, U+2264-U+2265, U+22F2, U+25CA, U+3007, U+4E00, U+4E03, U+4E09, U+4E5D, U+4E8C, U+4E94, U+516B, U+516D, U+5341, U+56D7, U+56DB, U+571F, U+6728, U+6C34, U+706B, U+91D1, U+F000-U+F002. The codepoints which are mapped to something else are the following: " " (U+20): No pa
 th but full advance; "p" (U+70): Path has 0 ascent but full descent; "\xC9" (U+C9): Path has 0 descent but full ascent; Non-breaking space (U+A0): No path b
 ut full advance; Zero-width non-breaking space (U+FEFF): No path and 0 advance; En space (U+2002): No path and half advance; Em space (U+2003): No path but full advance; Three-per-em space (U+2004): No path and one third advance; Four-per-em space (U+2005): No path and one quarter advance; Six-per-em space (U+2006): No path and one
  sixth advance; Thin space (U+2009): No path and one fifth advance; Hair space (U+200A): No path and one tenth advance; Zero width space (U+200B): No path and no adva
 nce; Ideographic space (U+3000): No path but full advance; Zero width non-joiner (U+200C): No path and no advance; Zero width joiner (U+200D): No path and no advance; Greek capital letter Chi (U+3A7): Thin horizontal stripe and full advance; (U+6A2A): Thin horizontal stripe and full advance; Greek capital letter Upsilon (U+3A5): T
 hin vertical stripe and full advance; (U+7EB5): Thin vertical stripe and full advance.http://www.w3c.orghttp://dev.w3.org/CSS/fonts/ahem/COPYING
+AhemRegularAhem\xFF{	+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x80\x81\x83\x84\x85\x86\x88\x89\x8A\x8B\x8D\x8E\x90\x91\x93\x96\x97\x9D\x9E\xA0\xA1\xA2\xA3\xA4\xA9\xAA\xAC\xAD\xAE\xAF\xB6\xB7\xB8\xBA\xBD\xC3\xC7\xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xDB\xDC\xDD\xDE\xDF\xE0\xE1\xE8\xE9\xEA\xEB\xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xB0\xB1\xBB\x
 A6\xA8\x9F\x9B\xB2\xB3\xC4\xB4\xB5\xC5\x82\xC2\x87\xAB\xC6\xBE\xBF\xBC\x8C\x98\x9A\x99\xA5\x92\x9C\x8F\x94\x95\xA7\xB9\xD2\xC0\xC1	
++ !"#$%&'(NULLglyph243glyph204glyph205HTDELuniFEFFuni2002uni2003uni2004uni2005uni2006uni2009uni200Auni200Buni3000	afii61664afii301uni4E00uni4E8Cuni4E09uni56DBuni4E94uni516Duni4E03uni516Buni4E5Duni5341uni3007uni56D7uni706Buni6C34uni6728uni91D1uni571Funi03A7uni6A2Auni03A5uni7EB5
\ No newline at end of file

Added: trunk/LayoutTests/fast/text/zwj-ligature-expected.html (0 => 281389)


--- trunk/LayoutTests/fast/text/zwj-ligature-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/zwj-ligature-expected.html	2021-08-22 05:41:27 UTC (rev 281389)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+    font-family: "WebFont";
+    src: url("resources/Ahem-GSUB-ligatures.ttf") format("truetype");
+}
+</style>
+</head>
+<body>
+This test makes sure that ligatures involving the Zero Width Joiner character work correctly. The test passes if you see a particular pattern of squares and horizontal lines below.
+<div style="font: 48px 'WebFont';">p p C p</div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/text/zwj-ligature.html (0 => 281389)


--- trunk/LayoutTests/fast/text/zwj-ligature.html	                        (rev 0)
+++ trunk/LayoutTests/fast/text/zwj-ligature.html	2021-08-22 05:41:27 UTC (rev 281389)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+    font-family: "WebFont";
+    src: url("resources/Ahem-GSUB-ligatures.ttf") format("truetype");
+}
+</style>
+</head>
+<body>
+This test makes sure that ligatures involving the Zero Width Joiner character work correctly. The test passes if you see a particular pattern of squares and horizontal lines below.
+<div style="font: 48px 'WebFont';">B&zwj; p C AB</div>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/mac/fast/text/format-control-expected.txt (281388 => 281389)


--- trunk/LayoutTests/platform/mac/fast/text/format-control-expected.txt	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/LayoutTests/platform/mac/fast/text/format-control-expected.txt	2021-08-22 05:41:27 UTC (rev 281389)
@@ -14,8 +14,8 @@
           RenderText {#text} at (0,0) size 290x46
             text run at (0,0) width 290: "f\x{200C}i f\x{200C}l f\x{200C}f f\x{200C}f\x{200C}i f\x{200C}f\x{200C}l f\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}l f\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C} \x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C} \x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C} \x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}\x{200C}i"
         RenderBlock {P} at (0,172) size 784x46
-          RenderText {#text} at (0,0) size 290x46
-            text run at (0,0) width 290: "f\x{200D}i f\x{200D}l f\x{200D}f f\x{200D}f\x{200D}i f\x{200D}f\x{200D}l f\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}l f\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D} \x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D} \x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D} \x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}i"
+          RenderText {#text} at (0,0) size 282x46
+            text run at (0,0) width 282: "f\x{200D}i f\x{200D}l f\x{200D}f f\x{200D}f\x{200D}i f\x{200D}f\x{200D}l f\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}l f\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D} \x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D} \x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D} \x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}\x{200D}i"
       RenderBlock {DIV} at (0,316) size 784x221
         RenderBlock {P} at (0,0) size 784x47
           RenderText {#text} at (0,1) size 288x45

Modified: trunk/LayoutTests/platform/win/TestExpectations (281388 => 281389)


--- trunk/LayoutTests/platform/win/TestExpectations	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/LayoutTests/platform/win/TestExpectations	2021-08-22 05:41:27 UTC (rev 281389)
@@ -4689,3 +4689,5 @@
 webkit.org/b/229372 http/tests/websocket/tests/hybi/inspector/send-and-recieve-debugger.html [ Skip ]
 
 webkit.org/b/229379 fast/visual-viewport/resize-event-fired-window-resized.html [ Skip ]
+
+webkit.org/b/215318 fast/text/zwj-ligature.html [ ImageOnlyFailure ]

Modified: trunk/Source/WTF/ChangeLog (281388 => 281389)


--- trunk/Source/WTF/ChangeLog	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WTF/ChangeLog	2021-08-22 05:41:27 UTC (rev 281389)
@@ -1,3 +1,13 @@
+2021-08-21  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        overwriteCodePoint() in createAndFillGlyphPage() is wrong
+        https://bugs.webkit.org/show_bug.cgi?id=215643
+        <rdar://problem/67430461>
+
+        Reviewed by Alan Bujtas.
+
+        * wtf/unicode/CharacterNames.h:
+
 2021-08-21  Sihui Liu  <sihui_...@apple.com>
 
         IndexedDB: crash when triggering IDBOpenRequest completion back on a worker thread

Modified: trunk/Source/WTF/wtf/unicode/CharacterNames.h (281388 => 281389)


--- trunk/Source/WTF/wtf/unicode/CharacterNames.h	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WTF/wtf/unicode/CharacterNames.h	2021-08-22 05:41:27 UTC (rev 281389)
@@ -51,6 +51,7 @@
 constexpr UChar byteOrderMark = 0xFEFF;
 constexpr UChar carriageReturn = 0x000D;
 constexpr UChar combiningEnclosingKeycap = 0x20E3;
+constexpr UChar deleteCharacter = 0x007F;
 constexpr UChar ethiopicPrefaceColon = 0x1366;
 constexpr UChar ethiopicWordspace = 0x1361;
 constexpr UChar firstStrongIsolate = 0x2068;
@@ -76,6 +77,7 @@
 constexpr UChar narrowNonBreakingSpace = 0x202F;
 constexpr UChar newlineCharacter = 0x000A;
 constexpr UChar noBreakSpace = 0x00A0;
+constexpr UChar nullCharacter = 0x0;
 constexpr UChar objectReplacementCharacter = 0xFFFC;
 constexpr UChar optionKey = 0x2325;
 constexpr UChar popDirectionalFormatting = 0x202C;
@@ -126,6 +128,7 @@
 using WTF::Unicode::byteOrderMark;
 using WTF::Unicode::carriageReturn;
 using WTF::Unicode::combiningEnclosingKeycap;
+using WTF::Unicode::deleteCharacter;
 using WTF::Unicode::ethiopicPrefaceColon;
 using WTF::Unicode::ethiopicWordspace;
 using WTF::Unicode::firstStrongIsolate;
@@ -151,6 +154,7 @@
 using WTF::Unicode::narrowNonBreakingSpace;
 using WTF::Unicode::newlineCharacter;
 using WTF::Unicode::noBreakSpace;
+using WTF::Unicode::nullCharacter;
 using WTF::Unicode::objectReplacementCharacter;
 using WTF::Unicode::popDirectionalFormatting;
 using WTF::Unicode::popDirectionalIsolate;

Modified: trunk/Source/WebCore/ChangeLog (281388 => 281389)


--- trunk/Source/WebCore/ChangeLog	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WebCore/ChangeLog	2021-08-22 05:41:27 UTC (rev 281389)
@@ -1,3 +1,43 @@
+2021-08-21  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        overwriteCodePoint() in createAndFillGlyphPage() is wrong
+        https://bugs.webkit.org/show_bug.cgi?id=215643
+        <rdar://problem/67430461>
+
+        Reviewed by Alan Bujtas.
+
+        The CSS spec says that certain characters have to be invisible. Previously, we were doing this
+        by just treating these characters as if they were the zero width space character. However, this
+        is wrong for 2 reasons:
+
+        1. If the primary font supports the desired character but doesn't support the zero width space
+               character, we'll fallback past it and trigger a download for secondary fonts until
+               we find one that supports the ZWS character (which the page didn't even ask for!)
+        2. Shaping is Turing-complete, and expects that the correct glyphIDs are fed into the shaper.
+               We can't just arbitrarily swap out glyphIDs before shaping just because we feel like it.
+
+        Instead, the solution is to handle these invisible characters after font fallback, and after
+        shaping. This patch does it just like we handle adding letter-spacing, word-spacing, and
+        justification after shaping - by iterating over the glyphs output by the shaper and seeing if
+        any need to be adjusted.
+
+        This patch also includes a fix for the situation where the glyph buffer might be left in an
+        inconsistent state, where the array of glyphs is shorter than the array of characters -
+        this new codepath added in this patch revealed this existing problem, and fixes it here too.
+
+        Test: fast/text/zwj-ligature.html
+
+        * platform/graphics/Font.cpp:
+        (WebCore::createAndFillGlyphPage):
+        (WebCore::overrideControlCharacters): Deleted.
+        * platform/graphics/GlyphBuffer.h:
+        (WebCore::GlyphBuffer::glyphAt const):
+        (WebCore::GlyphBuffer::deleteGlyphWithoutAffectingSize):
+        * platform/graphics/WidthIterator.cpp:
+        (WebCore::WidthIterator::applyCSSVisibilityRules):
+        (WebCore::WidthIterator::advance):
+        * platform/graphics/WidthIterator.h:
+
 2021-08-21  Alan Bujtas  <za...@apple.com>
 
         [LFC][Integration] Do not create an InlineFormattingContext object for constructing display lines and runs

Modified: trunk/Source/WebCore/platform/graphics/Font.cpp (281388 => 281389)


--- trunk/Source/WebCore/platform/graphics/Font.cpp	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WebCore/platform/graphics/Font.cpp	2021-08-22 05:41:27 UTC (rev 281389)
@@ -306,7 +306,7 @@
     return result;
 }
 
-#if !USE(FREETYPE)
+#if PLATFORM(WIN)
 static void overrideControlCharacters(Vector<UChar>& buffer, unsigned start, unsigned end)
 {
     auto overwriteCodePoints = [&](unsigned minimum, unsigned maximum, UChar newCodePoint) {
@@ -364,13 +364,13 @@
     unsigned start = GlyphPage::startingCodePointInPageNumber(pageNumber);
     Vector<UChar> buffer(glyphPageSize * 2 + 2);
     unsigned bufferLength;
-    // Fill in a buffer with the entire "page" of characters that we want to look up glyphs for.
     if (U_IS_BMP(start)) {
         bufferLength = glyphPageSize;
         for (unsigned i = 0; i < bufferLength; i++)
             buffer[i] = start + i;
 
-#if !USE(FREETYPE)
+#if PLATFORM(WIN)
+        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=215318 Delete this and use https://bugs.webkit.org/show_bug.cgi?id=215643 on Windows.
         overrideControlCharacters(buffer, start, start + glyphPageSize);
 #endif
     } else {

Modified: trunk/Source/WebCore/platform/graphics/GlyphBuffer.h (281388 => 281389)


--- trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2021-08-22 05:41:27 UTC (rev 281389)
@@ -71,7 +71,7 @@
         ASSERT(m_fonts[index]);
         return *m_fonts[index];
     }
-    Glyph glyphAt(unsigned index) const { return m_glyphs[index]; }
+    GlyphBufferGlyph glyphAt(unsigned index) const { return m_glyphs[index]; }
     GlyphBufferAdvance advanceAt(unsigned index) const { return m_advances[index]; }
     GlyphBufferOrigin originAt(unsigned index) const { return m_origins[index]; }
     GlyphBufferStringOffset uncheckedStringOffsetAt(unsigned index) const { return m_offsetsInString[index]; }
@@ -117,6 +117,14 @@
         m_offsetsInString.remove(location, length);
     }
 
+    void deleteGlyphWithoutAffectingSize(unsigned index)
+    {
+        // GlyphID 0xFFFF is the "deleted glyph" and is supposed to be invisible when rendered.
+        static const constexpr GlyphBufferGlyph deletedGlyph = 0xFFFF;
+        m_glyphs[index] = deletedGlyph;
+        m_advances[index] = makeGlyphBufferAdvance();
+    }
+
     void makeHole(unsigned location, unsigned length, const Font* font)
     {
         ASSERT(location <= size());

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.cpp (281388 => 281389)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.cpp	2021-08-22 05:41:27 UTC (rev 281389)
@@ -515,6 +515,64 @@
     }
 }
 
+void WidthIterator::applyCSSVisibilityRules(GlyphBuffer& glyphBuffer, unsigned glyphBufferStartIndex)
+{
+    Vector<unsigned> glyphsIndicesToBeDeleted;
+
+    float yPosition = height(glyphBuffer.initialAdvance());
+    for (unsigned i = glyphBufferStartIndex; i < glyphBuffer.size(); yPosition += height(glyphBuffer.advanceAt(i)), ++i) {
+        auto stringOffset = glyphBuffer.checkedStringOffsetAt(i, m_run.length());
+        if (!stringOffset)
+            continue;
+        auto characterResponsibleForThisGlyph = m_run[stringOffset.value()];
+
+        switch (characterResponsibleForThisGlyph) {
+        case newlineCharacter:
+        case carriageReturn:
+        case tabCharacter:
+        case noBreakSpace:
+            ASSERT(glyphBuffer.fonts(i)[0]);
+            // FIXME: Is this actually necessary? If the font specifically has a glyph for NBSP, I don't see a reason not to use it.
+            glyphBuffer.glyphs(i)[0] = glyphBuffer.fonts(i)[0]->spaceGlyph();
+            continue;
+        }
+
+        // FIXME: "Control characters (Unicode category Cc)—other than tabs (U+0009), line feeds (U+000A), carriage returns (U+000D) and sequences that form a segment break—must be rendered as a visible glyph"
+        // https://www.w3.org/TR/css-text-3/#white-space-processing
+
+        if ((characterResponsibleForThisGlyph >= nullCharacter && characterResponsibleForThisGlyph < space)
+            || (characterResponsibleForThisGlyph >= deleteCharacter && characterResponsibleForThisGlyph < noBreakSpace)) {
+            m_runWidthSoFar -= width(glyphBuffer.advanceAt(i));
+            glyphBuffer.deleteGlyphWithoutAffectingSize(i);
+            continue;
+        }
+
+        switch (characterResponsibleForThisGlyph) {
+        case softHyphen:
+        case leftToRightMark:
+        case rightToLeftMark:
+        case leftToRightEmbed:
+        case rightToLeftEmbed:
+        case leftToRightOverride:
+        case rightToLeftOverride:
+        case leftToRightIsolate:
+        case rightToLeftIsolate:
+        case zeroWidthNonJoiner:
+        case zeroWidthJoiner:
+        case popDirectionalFormatting:
+        case popDirectionalIsolate:
+        case firstStrongIsolate:
+        case objectReplacementCharacter:
+        case zeroWidthNoBreakSpace:
+            m_runWidthSoFar -= width(glyphBuffer.advanceAt(i));
+            glyphBuffer.deleteGlyphWithoutAffectingSize(i);
+            continue;
+        }
+    }
+
+    
+}
+
 void WidthIterator::finalize(GlyphBuffer& buffer)
 {
     ASSERT(m_run.rtl() || !m_leftoverJustificationWidth);
@@ -559,6 +617,8 @@
 
     if (hasExtraSpacing() || m_containsTabs || m_run.horizontalGlyphStretch() != 1)
         applyExtraSpacingAfterShaping(glyphBuffer, characterStartIndex, glyphBufferStartIndex, offset, startingRunWidth);
+
+    applyCSSVisibilityRules(glyphBuffer, glyphBufferStartIndex);
 }
 
 bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer)

Modified: trunk/Source/WebCore/platform/graphics/WidthIterator.h (281388 => 281389)


--- trunk/Source/WebCore/platform/graphics/WidthIterator.h	2021-08-22 04:28:58 UTC (rev 281388)
+++ trunk/Source/WebCore/platform/graphics/WidthIterator.h	2021-08-22 05:41:27 UTC (rev 281389)
@@ -73,6 +73,8 @@
 
     bool hasExtraSpacing() const;
     void applyExtraSpacingAfterShaping(GlyphBuffer&, unsigned characterStartIndex, unsigned glyphBufferStartIndex, unsigned characterDestinationIndex, float startingRunWidth);
+    void applyCSSVisibilityRules(GlyphBuffer&, unsigned glyphBufferStartIndex);
+
     struct AdditionalWidth {
         float left;
         float right;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to