[Cocoa] Glyph lookup should be language-sensitive (specifically between Yiddish and Hebrew)
https://bugs.webkit.org/show_bug.cgi?id=77568
<rdar://problem/14649193>
Reviewed by Simon Fraser.
Source/WebCore:
Switch from CTFontTransformGlyphs() to CTFontTransformGlyphsWithLanguage().
CTFontTransformGlyphsWithLanguage() accepts a callback when it needs to insert
glyphs and the glyph buffer isn't big enough. This patch hooks up this callback to
a "makeHole()" function which reallocs the glyph buffer so the hole can be filled in
by shaping.
We cache the CFDictionaries of the CFAttributedString we pass into CoreText using a
HashMap stored in Font.
Tests: fast/text/locale-shaping-complex.html
fast/text/locale-shaping.html
* platform/graphics/Font.cpp:
(WebCore::Font::applyTransforms const):
* platform/graphics/Font.h:
(WebCore::Font::CFStringAttributesKey::CFStringAttributesKey):
(WebCore::Font::CFStringAttributesKey::operator== const):
(WebCore::Font::CFStringAttributesKey::operator!= const):
(WebCore::Font::CFStringAttributesKey::isHashTableDeletedValue const):
(WebCore::Font::CFStringAttributesKey::computeHash const):
(WebCore::Font::CFStringAttributesKeyHash::hash):
(WebCore::Font::CFStringAttributesKeyHash::equal):
* platform/graphics/FontCascade.cpp:
(WebCore::FontCascade::widthForSimpleText const):
* platform/graphics/GlyphBuffer.h:
(WebCore::GlyphBuffer::isEmpty const):
(WebCore::GlyphBuffer::size const):
(WebCore::GlyphBuffer::clear):
(WebCore::GlyphBuffer::advances const):
(WebCore::GlyphBuffer::fontAt const):
(WebCore::GlyphBuffer::add):
(WebCore::GlyphBuffer::remove):
(WebCore::GlyphBuffer::makeHole):
(WebCore::GlyphBuffer::shrink):
(WebCore::GlyphBuffer::swap):
(WebCore::GlyphBuffer::advancesCount const): Deleted.
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::applyFontTransforms):
* platform/graphics/WidthIterator.h:
* platform/graphics/cocoa/FontCocoa.mm:
(WebCore::Font::applyTransforms const):
* platform/graphics/mac/ComplexTextControllerCoreText.mm:
(WebCore::ComplexTextController::collectComplexTextRunsForCharacters):
* platform/graphics/mac/SimpleFontDataCoreText.cpp:
(WebCore::Font::getCFStringAttributes const):
Source/WebCore/PAL:
* pal/spi/cocoa/CoreTextSPI.h:
Source/WTF:
* wtf/Platform.h:
LayoutTests:
* fast/text/locale-shaping-complex-expected-mismatch.html: Added.
* fast/text/locale-shaping-complex.html: Added.
* fast/text/locale-shaping-expected-mismatch.html: Added.
* fast/text/locale-shaping.html: Added.
* platform/gtk/TestExpectations:
* platform/mac/TestExpectations:
* platform/win/TestExpectations:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254534 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 4931841..dd926cc 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,19 @@
+2020-01-14 Myles C. Maxfield <mmaxfield@apple.com>
+
+ [Cocoa] Glyph lookup should be language-sensitive (specifically between Yiddish and Hebrew)
+ https://bugs.webkit.org/show_bug.cgi?id=77568
+ <rdar://problem/14649193>
+
+ Reviewed by Simon Fraser.
+
+ * fast/text/locale-shaping-complex-expected-mismatch.html: Added.
+ * fast/text/locale-shaping-complex.html: Added.
+ * fast/text/locale-shaping-expected-mismatch.html: Added.
+ * fast/text/locale-shaping.html: Added.
+ * platform/gtk/TestExpectations:
+ * platform/mac/TestExpectations:
+ * platform/win/TestExpectations:
+
2020-01-14 Lauro Moura <lmoura@igalia.com>
Gardening after r251750
diff --git a/LayoutTests/fast/text/locale-shaping-complex-expected-mismatch.html b/LayoutTests/fast/text/locale-shaping-complex-expected-mismatch.html
new file mode 100644
index 0000000..63e0b3e
--- /dev/null
+++ b/LayoutTests/fast/text/locale-shaping-complex-expected-mismatch.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<div lang="arab" style="font: 100px 'Comic Sans MS';">ííÀ</div>
+</body>
+</html>
diff --git a/LayoutTests/fast/text/locale-shaping-complex.html b/LayoutTests/fast/text/locale-shaping-complex.html
new file mode 100644
index 0000000..d6c9365
--- /dev/null
+++ b/LayoutTests/fast/text/locale-shaping-complex.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<div lang="lt" style="font: 100px 'Comic Sans MS';">ííÀ</div>
+</body>
+</html>
diff --git a/LayoutTests/fast/text/locale-shaping-expected-mismatch.html b/LayoutTests/fast/text/locale-shaping-expected-mismatch.html
new file mode 100644
index 0000000..6be6abf
--- /dev/null
+++ b/LayoutTests/fast/text/locale-shaping-expected-mismatch.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<div lang="arab" style="font: 100px 'Comic Sans MS';">íí</div>
+</body>
+</html>
diff --git a/LayoutTests/fast/text/locale-shaping.html b/LayoutTests/fast/text/locale-shaping.html
new file mode 100644
index 0000000..a520582
--- /dev/null
+++ b/LayoutTests/fast/text/locale-shaping.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+<div lang="lt" style="font: 100px 'Comic Sans MS';">íí</div>
+</body>
+</html>
diff --git a/LayoutTests/platform/gtk/TestExpectations b/LayoutTests/platform/gtk/TestExpectations
index 4adc734..e446e32 100644
--- a/LayoutTests/platform/gtk/TestExpectations
+++ b/LayoutTests/platform/gtk/TestExpectations
@@ -1206,6 +1206,10 @@
webkit.org/b/206223 imported/mozilla/svg/svg-integration/clipPath-html-02.xhtml
+# locale-specific shaping isn't implemented on any non-Cocoa port yet.
+webkit.org/b/77568 fast/text/locale-shaping.html [ ImageOnlyFailure ]
+webkit.org/b/77568 fast/text/locale-shaping-complex.html [ ImageOnlyFailure ]
+
#////////////////////////////////////////////////////////////////////////////////////////
# End of Expected failures.
#
diff --git a/LayoutTests/platform/mac/TestExpectations b/LayoutTests/platform/mac/TestExpectations
index 7cf660d..c244231 100644
--- a/LayoutTests/platform/mac/TestExpectations
+++ b/LayoutTests/platform/mac/TestExpectations
@@ -1928,4 +1928,8 @@
# The navigator.language tests rely on functionality only available in recent releases of macOS Catalina and onward.
webkit.org/b/200043 [ Sierra HighSierra Mojave Catalina ] fast/text/international/system-language/navigator-language [ Pass Failure ]
-webkit.org/b/204312 imported/w3c/web-platform-tests/svg/import/struct-dom-06-b-manual.svg [ Failure Pass ]
\ No newline at end of file
+webkit.org/b/204312 imported/w3c/web-platform-tests/svg/import/struct-dom-06-b-manual.svg [ Failure Pass ]
+
+# Locale-specific shaping is only enabled on certain OSes.
+webkit.org/b/77568 [ Sierra HighSierra Mojave ] fast/text/locale-shaping.html [ ImageOnlyFailure ]
+webkit.org/b/77568 [ Sierra HighSierra Mojave ] fast/text/locale-shaping-complex.html [ ImageOnlyFailure ]
diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations
index 1e71373..50f247d 100644
--- a/LayoutTests/platform/win/TestExpectations
+++ b/LayoutTests/platform/win/TestExpectations
@@ -689,6 +689,10 @@
fast/visual-viewport/client-coordinates-relative-to-layout-viewport.html [ Failure ]
fast/visual-viewport/zoomed-fixed-scroll-down-then-up.html [ Failure ]
+# locale-specific shaping isn't implemented on any non-Cocoa port yet.
+webkit.org/b/77568 fast/text/locale-shaping.html [ ImageOnlyFailure ]
+webkit.org/b/77568 fast/text/locale-shaping-complex.html [ ImageOnlyFailure ]
+
################################################################################
########### End Missing Functionality Prevents Testing ##############
################################################################################
diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog
index fce9626..fd45cab 100644
--- a/Source/WTF/ChangeLog
+++ b/Source/WTF/ChangeLog
@@ -1,3 +1,13 @@
+2020-01-14 Myles C. Maxfield <mmaxfield@apple.com>
+
+ [Cocoa] Glyph lookup should be language-sensitive (specifically between Yiddish and Hebrew)
+ https://bugs.webkit.org/show_bug.cgi?id=77568
+ <rdar://problem/14649193>
+
+ Reviewed by Simon Fraser.
+
+ * wtf/Platform.h:
+
2020-01-13 Darin Adler <darin@apple.com>
Use even more "shortest form" formatting, and less "fixed precision" and "fixed width"
diff --git a/Source/WTF/wtf/Platform.h b/Source/WTF/wtf/Platform.h
index c8a0afd..dad3825 100644
--- a/Source/WTF/wtf/Platform.h
+++ b/Source/WTF/wtf/Platform.h
@@ -917,6 +917,10 @@
#define HAVE_CTFONTCREATEFORCHARACTERSWITHLANGUAGEANDOPTION 1
#endif
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
+#define HAVE_CTFONTTRANSFORMGLYPHSWITHLANGUAGE 1
+#endif
+
#if PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
#define HAVE_ARKIT_QUICK_LOOK_PREVIEW_ITEM 1
#endif
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index f7131d6..ef90cb9 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,58 @@
+2020-01-14 Myles C. Maxfield <mmaxfield@apple.com>
+
+ [Cocoa] Glyph lookup should be language-sensitive (specifically between Yiddish and Hebrew)
+ https://bugs.webkit.org/show_bug.cgi?id=77568
+ <rdar://problem/14649193>
+
+ Reviewed by Simon Fraser.
+
+ Switch from CTFontTransformGlyphs() to CTFontTransformGlyphsWithLanguage().
+
+ CTFontTransformGlyphsWithLanguage() accepts a callback when it needs to insert
+ glyphs and the glyph buffer isn't big enough. This patch hooks up this callback to
+ a "makeHole()" function which reallocs the glyph buffer so the hole can be filled in
+ by shaping.
+
+ We cache the CFDictionaries of the CFAttributedString we pass into CoreText using a
+ HashMap stored in Font.
+
+ Tests: fast/text/locale-shaping-complex.html
+ fast/text/locale-shaping.html
+
+ * platform/graphics/Font.cpp:
+ (WebCore::Font::applyTransforms const):
+ * platform/graphics/Font.h:
+ (WebCore::Font::CFStringAttributesKey::CFStringAttributesKey):
+ (WebCore::Font::CFStringAttributesKey::operator== const):
+ (WebCore::Font::CFStringAttributesKey::operator!= const):
+ (WebCore::Font::CFStringAttributesKey::isHashTableDeletedValue const):
+ (WebCore::Font::CFStringAttributesKey::computeHash const):
+ (WebCore::Font::CFStringAttributesKeyHash::hash):
+ (WebCore::Font::CFStringAttributesKeyHash::equal):
+ * platform/graphics/FontCascade.cpp:
+ (WebCore::FontCascade::widthForSimpleText const):
+ * platform/graphics/GlyphBuffer.h:
+ (WebCore::GlyphBuffer::isEmpty const):
+ (WebCore::GlyphBuffer::size const):
+ (WebCore::GlyphBuffer::clear):
+ (WebCore::GlyphBuffer::advances const):
+ (WebCore::GlyphBuffer::fontAt const):
+ (WebCore::GlyphBuffer::add):
+ (WebCore::GlyphBuffer::remove):
+ (WebCore::GlyphBuffer::makeHole):
+ (WebCore::GlyphBuffer::shrink):
+ (WebCore::GlyphBuffer::swap):
+ (WebCore::GlyphBuffer::advancesCount const): Deleted.
+ * platform/graphics/WidthIterator.cpp:
+ (WebCore::WidthIterator::applyFontTransforms):
+ * platform/graphics/WidthIterator.h:
+ * platform/graphics/cocoa/FontCocoa.mm:
+ (WebCore::Font::applyTransforms const):
+ * platform/graphics/mac/ComplexTextControllerCoreText.mm:
+ (WebCore::ComplexTextController::collectComplexTextRunsForCharacters):
+ * platform/graphics/mac/SimpleFontDataCoreText.cpp:
+ (WebCore::Font::getCFStringAttributes const):
+
2020-01-14 Ross Kirsling <ross.kirsling@sony.com>
[PlayStation] Add standardUserAgentForURL stub
diff --git a/Source/WebCore/PAL/ChangeLog b/Source/WebCore/PAL/ChangeLog
index 9636e62..1679eb1 100644
--- a/Source/WebCore/PAL/ChangeLog
+++ b/Source/WebCore/PAL/ChangeLog
@@ -1,3 +1,13 @@
+2020-01-14 Myles C. Maxfield <mmaxfield@apple.com>
+
+ [Cocoa] Glyph lookup should be language-sensitive (specifically between Yiddish and Hebrew)
+ https://bugs.webkit.org/show_bug.cgi?id=77568
+ <rdar://problem/14649193>
+
+ Reviewed by Simon Fraser.
+
+ * pal/spi/cocoa/CoreTextSPI.h:
+
2020-01-09 Eric Carlson <eric.carlson@apple.com>
Don't softlink AVCapture classes on watchOS or tvOS
diff --git a/Source/WebCore/PAL/pal/spi/cocoa/CoreTextSPI.h b/Source/WebCore/PAL/pal/spi/cocoa/CoreTextSPI.h
index da2a9d4..d0f81c2 100644
--- a/Source/WebCore/PAL/pal/spi/cocoa/CoreTextSPI.h
+++ b/Source/WebCore/PAL/pal/spi/cocoa/CoreTextSPI.h
@@ -92,6 +92,7 @@
extern const CFStringRef kCTFontCSSFamilySystemUI;
bool CTFontTransformGlyphs(CTFontRef, CGGlyph glyphs[], CGSize advances[], CFIndex count, CTFontTransformOptions);
+CGSize CTFontTransformGlyphsWithLanguage(CTFontRef, CGGlyph[], CGSize[], CFIndex count, CTFontTransformOptions, CFStringRef language, void (^handler)(CFRange, CGGlyph**, CGSize**));
CGSize CTRunGetInitialAdvance(CTRunRef);
CTLineRef CTLineCreateWithUniCharProvider(CTUniCharProviderCallback, CTUniCharDisposeCallback, void* refCon);
diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp
index 8979b25..d945a96 100644
--- a/Source/WebCore/platform/graphics/Font.cpp
+++ b/Source/WebCore/platform/graphics/Font.cpp
@@ -499,20 +499,11 @@
return platformCreateScaledFont(fontDescription, scaleFactor);
}
-bool Font::applyTransforms(GlyphBufferGlyph* glyphs, GlyphBufferAdvance* advances, size_t glyphCount, bool enableKerning, bool requiresShaping) const
+#if !PLATFORM(COCOA)
+void Font::applyTransforms(GlyphBuffer&, unsigned, bool, bool, const AtomString&) const
{
-#if PLATFORM(COCOA)
- CTFontTransformOptions options = (enableKerning ? kCTFontTransformApplyPositioning : 0) | (requiresShaping ? kCTFontTransformApplyShaping : 0);
- return CTFontTransformGlyphs(m_platformData.ctFont(), glyphs, reinterpret_cast<CGSize*>(advances), glyphCount, options);
-#else
- UNUSED_PARAM(glyphs);
- UNUSED_PARAM(advances);
- UNUSED_PARAM(glyphCount);
- UNUSED_PARAM(enableKerning);
- UNUSED_PARAM(requiresShaping);
- return false;
-#endif
}
+#endif
class CharacterFallbackMapKey {
public:
diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h
index 0c95259..03bf5ee 100644
--- a/Source/WebCore/platform/graphics/Font.h
+++ b/Source/WebCore/platform/graphics/Font.h
@@ -35,10 +35,12 @@
#include "OpenTypeVerticalData.h"
#endif
#include <wtf/BitVector.h>
+#include <wtf/Hasher.h>
#include <wtf/Optional.h>
#include <wtf/text/StringHash.h>
#if PLATFORM(COCOA)
+#include <CoreFoundation/CoreFoundation.h>
#include <wtf/RetainPtr.h>
#endif
@@ -196,7 +198,7 @@
#endif
#if PLATFORM(COCOA)
CTFontRef getCTFont() const { return m_platformData.font(); }
- CFDictionaryRef getCFStringAttributes(bool enableKerning, FontOrientation) const;
+ RetainPtr<CFDictionaryRef> getCFStringAttributes(bool enableKerning, FontOrientation, const AtomString& locale) const;
const BitVector& glyphsSupportedBySmallCaps() const;
const BitVector& glyphsSupportedByAllSmallCaps() const;
const BitVector& glyphsSupportedByPetiteCaps() const;
@@ -208,7 +210,7 @@
#endif
bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
- bool applyTransforms(GlyphBufferGlyph*, GlyphBufferAdvance*, size_t glyphCount, bool enableKerning, bool requiresShaping) const;
+ void applyTransforms(GlyphBuffer&, unsigned beginningIndex, bool enableKerning, bool requiresShaping, const AtomString& locale) const;
#if PLATFORM(WIN)
SCRIPT_FONTPROPERTIES* scriptFontProperties() const;
@@ -281,8 +283,6 @@
mutable std::unique_ptr<DerivedFonts> m_derivedFontData;
#if PLATFORM(COCOA)
- mutable RetainPtr<CFMutableDictionaryRef> m_nonKernedCFStringAttributes;
- mutable RetainPtr<CFMutableDictionaryRef> m_kernedCFStringAttributes;
mutable Optional<BitVector> m_glyphsSupportedBySmallCaps;
mutable Optional<BitVector> m_glyphsSupportedByAllSmallCaps;
mutable Optional<BitVector> m_glyphsSupportedByPetiteCaps;
diff --git a/Source/WebCore/platform/graphics/FontCascade.cpp b/Source/WebCore/platform/graphics/FontCascade.cpp
index 8308f2b..5e5d038 100644
--- a/Source/WebCore/platform/graphics/FontCascade.cpp
+++ b/Source/WebCore/platform/graphics/FontCascade.cpp
@@ -416,6 +416,7 @@
if (cacheEntry && !std::isnan(*cacheEntry))
return *cacheEntry;
+ GlyphBuffer glyphBuffer;
Vector<GlyphBufferGlyph, 16> glyphs;
Vector<GlyphBufferAdvance, 16> advances;
bool hasKerningOrLigatures = enableKerning() || requiresShaping();
@@ -427,16 +428,15 @@
runWidth += glyphWidth;
if (!hasKerningOrLigatures)
continue;
- glyphs.append(glyph);
- advances.append(FloatSize(glyphWidth, 0));
+ glyphBuffer.add(glyph, &font, glyphWidth);
}
if (hasKerningOrLigatures) {
- font.applyTransforms(&glyphs[0], &advances[0], glyphs.size(), enableKerning(), requiresShaping());
+ font.applyTransforms(glyphBuffer, 0, enableKerning(), requiresShaping(), fontDescription().locale());
// This is needed only to match the result of the slow path. Same glyph widths but different floating point arithmentics can
// produce different run width.
float runWidthDifferenceWithTransformApplied = -runWidth;
- for (auto& advance : advances)
- runWidthDifferenceWithTransformApplied += advance.width();
+ for (size_t i = 0; i < glyphBuffer.size(); ++i)
+ runWidthDifferenceWithTransformApplied += glyphBuffer.advanceAt(i).width();
runWidth += runWidthDifferenceWithTransformApplied;
}
diff --git a/Source/WebCore/platform/graphics/GlyphBuffer.h b/Source/WebCore/platform/graphics/GlyphBuffer.h
index 7b56a37..db65233 100644
--- a/Source/WebCore/platform/graphics/GlyphBuffer.h
+++ b/Source/WebCore/platform/graphics/GlyphBuffer.h
@@ -100,12 +100,12 @@
class GlyphBuffer {
public:
- bool isEmpty() const { return m_font.isEmpty(); }
- unsigned size() const { return m_font.size(); }
+ bool isEmpty() const { return m_fonts.isEmpty(); }
+ unsigned size() const { return m_fonts.size(); }
void clear()
{
- m_font.clear();
+ m_fonts.clear();
m_glyphs.clear();
m_advances.clear();
if (m_offsetsInString)
@@ -116,9 +116,8 @@
GlyphBufferAdvance* advances(unsigned from) { return m_advances.data() + from; }
const GlyphBufferGlyph* glyphs(unsigned from) const { return m_glyphs.data() + from; }
const GlyphBufferAdvance* advances(unsigned from) const { return m_advances.data() + from; }
- size_t advancesCount() const { return m_advances.size(); }
- const Font* fontAt(unsigned index) const { return m_font[index]; }
+ const Font* fontAt(unsigned index) const { return m_fonts[index]; }
void setInitialAdvance(GlyphBufferAdvance initialAdvance) { m_initialAdvance = initialAdvance; }
const GlyphBufferAdvance& initialAdvance() const { return m_initialAdvance; }
@@ -145,7 +144,7 @@
void add(Glyph glyph, const Font* font, GlyphBufferAdvance advance, unsigned offsetInString)
{
- m_font.append(font);
+ m_fonts.append(font);
m_glyphs.append(glyph);
m_advances.append(advance);
@@ -154,6 +153,26 @@
m_offsetsInString->append(offsetInString);
}
+ void remove(unsigned location, unsigned length)
+ {
+ m_fonts.remove(location, length);
+ m_glyphs.remove(location, length);
+ m_advances.remove(location, length);
+ if (m_offsetsInString)
+ m_offsetsInString->remove(location, length);
+ }
+
+ void makeHole(unsigned location, unsigned length, const Font* font)
+ {
+ ASSERT(location <= size());
+
+ m_fonts.insertVector(location, Vector<const Font*>(length, font));
+ m_glyphs.insertVector(location, Vector<GlyphBufferGlyph>(length, 0xFFFF));
+ m_advances.insertVector(location, Vector<GlyphBufferAdvance>(length, GlyphBufferAdvance(0, 0)));
+ if (m_offsetsInString)
+ m_offsetsInString->insertVector(location, Vector<unsigned>(length, 0));
+ }
+
void reverse(unsigned from, unsigned length)
{
for (unsigned i = from, end = from + length - 1; i < end; ++i, --end)
@@ -188,7 +207,7 @@
void shrink(unsigned truncationPoint)
{
- m_font.shrink(truncationPoint);
+ m_fonts.shrink(truncationPoint);
m_glyphs.shrink(truncationPoint);
m_advances.shrink(truncationPoint);
if (m_offsetsInString)
@@ -198,9 +217,9 @@
private:
void swap(unsigned index1, unsigned index2)
{
- const Font* f = m_font[index1];
- m_font[index1] = m_font[index2];
- m_font[index2] = f;
+ const Font* f = m_fonts[index1];
+ m_fonts[index1] = m_fonts[index2];
+ m_fonts[index2] = f;
GlyphBufferGlyph g = m_glyphs[index1];
m_glyphs[index1] = m_glyphs[index2];
@@ -211,7 +230,7 @@
m_advances[index2] = s;
}
- Vector<const Font*, 2048> m_font;
+ Vector<const Font*, 2048> m_fonts;
Vector<GlyphBufferGlyph, 2048> m_glyphs;
Vector<GlyphBufferAdvance, 2048> m_advances;
GlyphBufferAdvance m_initialAdvance;
diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp
index bcc86af..6e46d42 100644
--- a/Source/WebCore/platform/graphics/WidthIterator.cpp
+++ b/Source/WebCore/platform/graphics/WidthIterator.cpp
@@ -98,7 +98,7 @@
if (!glyphBuffer)
return 0;
- unsigned glyphBufferSize = glyphBuffer->size();
+ auto glyphBufferSize = glyphBuffer->size();
if (!force && glyphBufferSize <= lastGlyphCount + 1) {
lastGlyphCount = glyphBufferSize;
return 0;
@@ -113,7 +113,8 @@
if (!ltr)
glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount);
- font->applyTransforms(glyphBuffer->glyphs(lastGlyphCount), advances + lastGlyphCount, glyphBufferSize - lastGlyphCount, m_enableKerning, m_requiresShaping);
+ font->applyTransforms(*glyphBuffer, lastGlyphCount, m_enableKerning, m_requiresShaping, m_font->fontDescription().locale());
+ glyphBufferSize = glyphBuffer->size();
for (unsigned i = lastGlyphCount; i < glyphBufferSize; ++i)
advances[i].setHeight(-advances[i].height());
@@ -121,8 +122,14 @@
if (!ltr)
glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount);
+ // https://bugs.webkit.org/show_bug.cgi?id=206208: This is totally, 100%, furiously, utterly, frustratingly bogus.
+ // There is absolutely no guarantee that glyph indices before shaping have any relation at all with glyph indices after shaping.
+ // One of the fundamental things that shaping does is insert glyph all over the place.
for (size_t i = 0; i < charactersTreatedAsSpace.size(); ++i) {
- int spaceOffset = charactersTreatedAsSpace[i].first;
+ auto spaceOffset = charactersTreatedAsSpace[i].first;
+ // Shaping may have deleted the glyph.
+ if (spaceOffset >= glyphBufferSize)
+ continue;
const OriginalAdvancesForCharacterTreatedAsSpace& originalAdvances = charactersTreatedAsSpace[i].second;
if (spaceOffset && !originalAdvances.characterIsSpace)
glyphBuffer->advances(spaceOffset - 1)->setWidth(originalAdvances.advanceBeforeCharacter);
diff --git a/Source/WebCore/platform/graphics/WidthIterator.h b/Source/WebCore/platform/graphics/WidthIterator.h
index c45fdb8..b2c509f 100644
--- a/Source/WebCore/platform/graphics/WidthIterator.h
+++ b/Source/WebCore/platform/graphics/WidthIterator.h
@@ -35,7 +35,7 @@
struct GlyphData;
struct OriginalAdvancesForCharacterTreatedAsSpace;
-typedef Vector<std::pair<int, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace;
+typedef Vector<std::pair<unsigned, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace;
struct WidthIterator {
WTF_MAKE_FAST_ALLOCATED;
diff --git a/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm b/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm
index de9a170..5a3352b 100644
--- a/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm
+++ b/Source/WebCore/platform/graphics/cocoa/FontCocoa.mm
@@ -543,6 +543,29 @@
return createDerivativeFont(scaledFont.get(), size, m_platformData.orientation(), fontTraits, m_platformData.syntheticBold(), m_platformData.syntheticOblique());
}
+void Font::applyTransforms(GlyphBuffer& glyphBuffer, unsigned beginningIndex, bool enableKerning, bool requiresShaping, const AtomString& locale) const
+{
+ // FIXME: Implement GlyphBuffer initial advance.
+ CTFontTransformOptions options = (enableKerning ? kCTFontTransformApplyPositioning : 0) | (requiresShaping ? kCTFontTransformApplyShaping : 0);
+#if HAVE(CTFONTTRANSFORMGLYPHSWITHLANGUAGE)
+ auto handler = ^(CFRange range, CGGlyph** newGlyphsPointer, CGSize** newAdvancesPointer) {
+ range.location = std::min(std::max(range.location, static_cast<CFIndex>(0)), static_cast<CFIndex>(glyphBuffer.size()));
+ if (range.length < 0) {
+ range.length = std::min(range.location, -range.length);
+ range.location = range.location - range.length;
+ glyphBuffer.remove(beginningIndex + range.location, range.length);
+ } else
+ glyphBuffer.makeHole(beginningIndex + range.location, range.length, this);
+ *newGlyphsPointer = glyphBuffer.glyphs(beginningIndex);
+ *newAdvancesPointer = glyphBuffer.advances(beginningIndex);
+ };
+ CTFontTransformGlyphsWithLanguage(m_platformData.ctFont(), glyphBuffer.glyphs(beginningIndex), reinterpret_cast<CGSize*>(glyphBuffer.advances(beginningIndex)), glyphBuffer.size() - beginningIndex, options, locale.string().createCFString().get(), handler);
+#else
+ UNUSED_PARAM(locale);
+ CTFontTransformGlyphs(m_platformData.ctFont(), glyphBuffer.glyphs(beginningIndex), reinterpret_cast<CGSize*>(glyphBuffer.advances(beginningIndex)), glyphBuffer.size() - beginningIndex, options);
+#endif
+}
+
static int extractNumber(CFNumberRef number)
{
int result = 0;
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
index 558a7dd..f3b5c13 100644
--- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
+++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm
@@ -128,11 +128,11 @@
font = m_font.fallbackRangesAt(0).fontForCharacter(baseCharacter);
if (!font)
font = &m_font.fallbackRangesAt(0).fontForFirstRange();
- stringAttributes = adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, font->getCFStringAttributes(m_font.enableKerning(), font->platformData().orientation())));
+ stringAttributes = adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, font->getCFStringAttributes(m_font.enableKerning(), font->platformData().orientation(), m_font.fontDescription().locale()).get()));
// We don't know which font should be used to render this grapheme cluster, so enable CoreText's fallback mechanism by using the CTFont which doesn't have CoreText's fallback disabled.
CFDictionarySetValue(const_cast<CFMutableDictionaryRef>(stringAttributes.get()), kCTFontAttributeName, font->platformData().font());
} else
- stringAttributes = font->getCFStringAttributes(m_font.enableKerning(), font->platformData().orientation());
+ stringAttributes = font->getCFStringAttributes(m_font.enableKerning(), font->platformData().orientation(), m_font.fontDescription().locale());
RetainPtr<CTLineRef> line;
diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
index 7103b69..8945124 100644
--- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
+++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp
@@ -32,15 +32,17 @@
namespace WebCore {
-CFDictionaryRef Font::getCFStringAttributes(bool enableKerning, FontOrientation orientation) const
+RetainPtr<CFDictionaryRef> Font::getCFStringAttributes(bool enableKerning, FontOrientation orientation, const AtomString& locale) const
{
- auto& attributesDictionary = enableKerning ? m_kernedCFStringAttributes : m_nonKernedCFStringAttributes;
- if (attributesDictionary)
- return attributesDictionary.get();
-
- attributesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ auto attributesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
CFDictionarySetValue(attributesDictionary.get(), kCTFontAttributeName, platformData().ctFont());
+#if HAVE(CTFONTTRANSFORMGLYPHSWITHLANGUAGE)
+ if (!locale.isEmpty())
+ CFDictionarySetValue(attributesDictionary.get(), kCTLanguageAttributeName, locale.string().createCFString().get());
+#else
+ UNUSED_PARAM(locale);
+#endif
auto paragraphStyle = adoptCF(CTParagraphStyleCreate(nullptr, 0));
CTParagraphStyleSetCompositionLanguage(paragraphStyle.get(), kCTCompositionLanguageNone);
CFDictionarySetValue(attributesDictionary.get(), kCTParagraphStyleAttributeName, paragraphStyle.get());
@@ -54,7 +56,7 @@
if (orientation == FontOrientation::Vertical)
CFDictionarySetValue(attributesDictionary.get(), kCTVerticalFormsAttributeName, kCFBooleanTrue);
- return attributesDictionary.get();
+ return attributesDictionary;
}
#if HAVE(DISALLOWABLE_USER_INSTALLED_FONTS)