[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 = "حلاح";
+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