[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

mitz at apple.com mitz at apple.com
Wed Apr 7 23:15:16 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 490a8c229984ec451708d1bcb4d58b6f14726794
Author: mitz at apple.com <mitz at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Oct 29 21:25:59 2009 +0000

    Problem editing or selecting text containing ligatures
    https://bugs.webkit.org/show_bug.cgi?id=30025
    
    Reviewed by Sam Weinig.
    
    WebCore:
    
    Test: platform/mac/fast/text/ligature-subdivision.html
    
    * platform/graphics/mac/ComplexTextController.cpp:
    (WebCore::ComplexTextController::ComplexTextController): Initialize
    m_characterInCurrentGlyph.
    (WebCore::ComplexTextController::offsetForPosition): If the hit glyph spans multiple
    characters, compute the hit character based on dividing the glyph’s total advance into
    a number of equal intervals equal to the number of characters and assigning the hit to the
    character corresponding to the hit interval.
    (WebCore::ComplexTextController::advance): If the final offset occurs mid-glyph, advance
    by a fraction of the glyph’s total advance.
    * platform/graphics/mac/ComplexTextController.h: Added m_characterInCurrentGlyph.
    
    LayoutTests:
    
    * platform/mac/fast/text/ligature-subdivision-expected.txt: Added.
    * platform/mac/fast/text/ligature-subdivision.html: Added.
    * platform/mac/fast/text/script-tests: Added.
    * platform/mac/fast/text/script-tests/TEMPLATE.html: Copied from LayoutTests/fast/js/script-tests/TEMPLATE.html.
    * platform/mac/fast/text/script-tests/ligature-subdivision.js: Added.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@50301 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 3847455..f3ea27e 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,16 @@
+2009-10-29  Dan Bernstein  <mitz at apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Problem editing or selecting text containing ligatures
+        https://bugs.webkit.org/show_bug.cgi?id=30025
+
+        * platform/mac/fast/text/ligature-subdivision-expected.txt: Added.
+        * platform/mac/fast/text/ligature-subdivision.html: Added.
+        * platform/mac/fast/text/script-tests: Added.
+        * platform/mac/fast/text/script-tests/TEMPLATE.html: Copied from LayoutTests/fast/js/script-tests/TEMPLATE.html.
+        * platform/mac/fast/text/script-tests/ligature-subdivision.js: Added.
+
 2009-10-29  Kenneth Rohde Christiansen  <kenneth at webkit.org>
 
         Rubberstamped by Adam Roben.
diff --git a/LayoutTests/platform/mac/fast/text/ligature-subdivision-expected.txt b/LayoutTests/platform/mac/fast/text/ligature-subdivision-expected.txt
new file mode 100644
index 0000000..1f2456f
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/text/ligature-subdivision-expected.txt
@@ -0,0 +1,21 @@
+Test that the caret is positioned correctly when its offset occurrs in the middle of a ligature, and that hit-testing in the middle of a ligature works correctly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.caretRangeFromPoint(10, y).startOffset is 0
+PASS document.caretRangeFromPoint(30, y).startOffset is 1
+PASS document.caretRangeFromPoint(60, y).startOffset is 2
+PASS document.caretRangeFromPoint(80, y).startOffset is 3
+PASS document.caretRangeFromPoint(100, y).startOffset is 4
+PASS document.caretRangeFromPoint(120, y).startOffset is 5
+PASS range.getBoundingClientRect().width is 80
+PASS document.caretRangeFromPoint(x - 20, y).startOffset is 0
+PASS document.caretRangeFromPoint(x - 50, y).startOffset is 1
+PASS document.caretRangeFromPoint(x - 64, y).startOffset is 2
+PASS document.caretRangeFromPoint(x - 90, y).startOffset is 3
+PASS range.getBoundingClientRect().width is 65
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/platform/mac/fast/text/ligature-subdivision.html b/LayoutTests/platform/mac/fast/text/ligature-subdivision.html
new file mode 100644
index 0000000..6d2ec64
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/text/ligature-subdivision.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
+<script src="../../../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/ligature-subdivision.js"></script>
+<script src="../../../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/platform/gtk/editing/pasteboard/script-tests/TEMPLATE.html b/LayoutTests/platform/mac/fast/text/script-tests/TEMPLATE.html
similarity index 100%
copy from LayoutTests/platform/gtk/editing/pasteboard/script-tests/TEMPLATE.html
copy to LayoutTests/platform/mac/fast/text/script-tests/TEMPLATE.html
diff --git a/LayoutTests/platform/mac/fast/text/script-tests/ligature-subdivision.js b/LayoutTests/platform/mac/fast/text/script-tests/ligature-subdivision.js
new file mode 100644
index 0000000..c1d7f73
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/text/script-tests/ligature-subdivision.js
@@ -0,0 +1,54 @@
+description('Test that the caret is positioned correctly when its offset occurrs in the middle of a ligature,\
+    and that hit-testing in the middle of a ligature works correctly.');
+
+var latin = document.createElement("div");
+latin.innerHTML = "office";
+latin.style.fontSize = "72px";
+latin.style.textRendering = "optimizelegibility";
+latin.style.position = "absolute";
+latin.style.top = "0";
+latin.style.left = "0";
+document.body.appendChild(latin);
+
+var y = latin.offsetTop + latin.offsetHeight / 2;
+
+document.body.offsetTop;
+
+shouldBe('document.caretRangeFromPoint(10, y).startOffset', '0');
+shouldBe('document.caretRangeFromPoint(30, y).startOffset', '1');
+shouldBe('document.caretRangeFromPoint(60, y).startOffset', '2');
+shouldBe('document.caretRangeFromPoint(80, y).startOffset', '3');
+shouldBe('document.caretRangeFromPoint(100, y).startOffset', '4');
+shouldBe('document.caretRangeFromPoint(120, y).startOffset', '5');
+
+var range = document.createRange();
+range.setStart(latin.firstChild, 0);
+range.setEnd(latin.firstChild, 3);
+shouldBe('range.getBoundingClientRect().width', '80');
+
+document.body.removeChild(latin);
+
+var arabic = document.createElement("div");
+arabic.innerHTML = "&#x062d;&#x0644;&#x0627;&#x062d;";
+arabic.style.fontSize = "72px";
+arabic.style.direction = "rtl";
+arabic.style.position = "absolute";
+arabic.style.top = "0";
+arabic.style.right = "0";
+document.body.appendChild(arabic);
+
+y = arabic.offsetTop + arabic.offsetHeight / 2;
+var x = arabic.offsetLeft + arabic.offsetWidth;
+
+shouldBe('document.caretRangeFromPoint(x - 20, y).startOffset', '0');
+shouldBe('document.caretRangeFromPoint(x - 50, y).startOffset', '1');
+shouldBe('document.caretRangeFromPoint(x - 64, y).startOffset', '2');
+shouldBe('document.caretRangeFromPoint(x - 90, y).startOffset', '3');
+
+range.setStart(arabic.firstChild, 0);
+range.setEnd(arabic.firstChild, 2);
+shouldBe('range.getBoundingClientRect().width', '65');
+
+document.body.removeChild(arabic);
+
+var successfullyParsed = true;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index f38e32f..508870e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,23 @@
+2009-10-29  Dan Bernstein  <mitz at apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Problem editing or selecting text containing ligatures
+        https://bugs.webkit.org/show_bug.cgi?id=30025
+
+        Test: platform/mac/fast/text/ligature-subdivision.html
+
+        * platform/graphics/mac/ComplexTextController.cpp:
+        (WebCore::ComplexTextController::ComplexTextController): Initialize
+        m_characterInCurrentGlyph.
+        (WebCore::ComplexTextController::offsetForPosition): If the hit glyph spans multiple
+        characters, compute the hit character based on dividing the glyph’s total advance into
+        a number of equal intervals equal to the number of characters and assigning the hit to the
+        character corresponding to the hit interval.
+        (WebCore::ComplexTextController::advance): If the final offset occurs mid-glyph, advance
+        by a fraction of the glyph’s total advance.
+        * platform/graphics/mac/ComplexTextController.h: Added m_characterInCurrentGlyph.
+
 2009-10-29  Brian Weinstein  <bweinstein at apple.com>
 
         Reviewed by Timothy Hatcher.
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp
index 826496b..265b2c3 100644
--- a/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -29,6 +29,8 @@
 #include "Font.h"
 #include "TextBreakIterator.h"
 
+using namespace std;
+
 namespace WebCore {
 
 static inline CGFloat roundCGFloat(CGFloat f)
@@ -56,6 +58,7 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
     , m_numGlyphsSoFar(0)
     , m_currentRun(0)
     , m_glyphInCurrentRun(0)
+    , m_characterInCurrentGlyph(0)
     , m_finalRoundingWidth(0)
     , m_fallbackFonts(fallbackFonts)
     , m_lastRoundingGlyph(0)
@@ -81,10 +84,6 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
 
 int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
 {
-    // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
-    // approximate it by dividing the width of the ligature by the number of characters it encompasses.
-    // However, Core Text does not expose a low-level API for directly finding
-    // out how many characters a ligature encompasses (the "attachment count").
     if (h >= m_totalWidth)
         return m_run.ltr() ? m_end : 0;
     if (h < 0)
@@ -99,8 +98,18 @@ int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
         const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
         for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
             CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
-            if (x <= adjustedAdvance) {
-                CFIndex hitIndex = complexTextRun.indexAt(j);
+            if (x < adjustedAdvance) {
+                CFIndex hitGlyphStart = complexTextRun.indexAt(j);
+                CFIndex hitGlyphEnd;
+                if (m_run.ltr())
+                    hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : complexTextRun.stringLength());
+                else
+                    hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.stringLength());
+
+                // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+                // could use the glyph's "ligature carets". However, there is no Core Text API to get the
+                // ligature carets.
+                CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
                 int stringLength = complexTextRun.stringLength();
                 TextBreakIterator* cursorPositionIterator = cursorMovementIterator(complexTextRun.characters(), stringLength);
                 int clusterStart;
@@ -119,11 +128,12 @@ int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
                 if (clusterEnd == TextBreakDone)
                     clusterEnd = stringLength;
 
-                CGFloat clusterWidth = adjustedAdvance;
+                CGFloat clusterWidth;
                 // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
                 // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
                 // reordering and on font fallback should occur within a CTLine.
                 if (clusterEnd - clusterStart > 1) {
+                    clusterWidth = adjustedAdvance;
                     int firstGlyphBeforeCluster = j - 1;
                     while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
                         CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
@@ -136,6 +146,9 @@ int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
                         clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
                         firstGlyphAfterCluster++;
                     }
+                } else {
+                    clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart);
+                    x -=  clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1);
                 }
                 if (x <= clusterWidth / 2)
                     return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
@@ -252,10 +265,6 @@ void ComplexTextController::collectComplexTextRuns()
 
 void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
 {
-    // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"
-    // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional
-    // to the offsets into the ligature. However, Core Text does not expose a low-level API for
-    // directly finding out how many characters a ligature encompasses (the "attachment count").
     if (static_cast<int>(offset) > m_end)
         offset = m_end;
 
@@ -274,14 +283,34 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
         size_t glyphCount = complexTextRun.glyphCount();
         unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
         while (m_glyphInCurrentRun < glyphCount) {
-            if (complexTextRun.indexAt(g) + complexTextRun.stringLocation() >= m_currentCharacter)
-                return;
+            unsigned glyphStartOffset = complexTextRun.indexAt(g);
+            unsigned glyphEndOffset;
+            if (ltr)
+                glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength());
+            else
+                glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength());
+
             CGSize adjustedAdvance = m_adjustedAdvances[k];
-            if (glyphBuffer)
+
+            if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
+                return;
+
+            if (glyphBuffer && !m_characterInCurrentGlyph)
                 glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
-            m_runWidthSoFar += adjustedAdvance.width;
+
+            unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
+            m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
+            // FIXME: Instead of dividing the glyph's advance equially between the characters, this
+            // could use the glyph's "ligature carets". However, there is no Core Text API to get the
+            // ligature carets.
+            m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
+
+            if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
+                return;
+
             m_numGlyphsSoFar++;
             m_glyphInCurrentRun++;
+            m_characterInCurrentGlyph = 0;
             if (ltr) {
                 g++;
                 k++;
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h
index 94bb64f..0beb108 100644
--- a/WebCore/platform/graphics/mac/ComplexTextController.h
+++ b/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -144,6 +144,7 @@ private:
     unsigned m_numGlyphsSoFar;
     size_t m_currentRun;
     unsigned m_glyphInCurrentRun;
+    unsigned m_characterInCurrentGlyph;
     float m_finalRoundingWidth;
     float m_padding;
     float m_padPerSpace;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list