Changeset 50301 in webkit


Ignore:
Timestamp:
Oct 29, 2009 2:25:59 PM (14 years ago)
Author:
mitz@apple.com
Message:

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.
Location:
trunk
Files:
4 added
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r50297 r50301  
     12009-10-29  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Problem editing or selecting text containing ligatures
     6        https://bugs.webkit.org/show_bug.cgi?id=30025
     7
     8        * platform/mac/fast/text/ligature-subdivision-expected.txt: Added.
     9        * platform/mac/fast/text/ligature-subdivision.html: Added.
     10        * platform/mac/fast/text/script-tests: Added.
     11        * platform/mac/fast/text/script-tests/TEMPLATE.html: Copied from LayoutTests/fast/js/script-tests/TEMPLATE.html.
     12        * platform/mac/fast/text/script-tests/ligature-subdivision.js: Added.
     13
    1142009-10-29  Kenneth Rohde Christiansen  <kenneth@webkit.org>
    215
  • trunk/LayoutTests/platform/mac/fast/text/script-tests/TEMPLATE.html

    r50299 r50301  
    22<html>
    33<head>
    4 <link rel="stylesheet" href="resources/js-test-style.css">
    5 <script src="resources/js-test-pre.js"></script>
     4<link rel="stylesheet" href="../../../../fast/js/resources/js-test-style.css">
     5<script src="../../../../fast/js/resources/js-test-pre.js"></script>
    66</head>
    77<body>
     
    99<div id="console"></div>
    1010<script src="YOUR_JS_FILE_HERE"></script>
    11 <script src="resources/js-test-post.js"></script>
     11<script src="../../../../fast/js/resources/js-test-post.js"></script>
    1212</body>
    1313</html>
  • trunk/WebCore/ChangeLog

    r50300 r50301  
     12009-10-29  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4
     5        Problem editing or selecting text containing ligatures
     6        https://bugs.webkit.org/show_bug.cgi?id=30025
     7
     8        Test: platform/mac/fast/text/ligature-subdivision.html
     9
     10        * platform/graphics/mac/ComplexTextController.cpp:
     11        (WebCore::ComplexTextController::ComplexTextController): Initialize
     12        m_characterInCurrentGlyph.
     13        (WebCore::ComplexTextController::offsetForPosition): If the hit glyph spans multiple
     14        characters, compute the hit character based on dividing the glyph’s total advance into
     15        a number of equal intervals equal to the number of characters and assigning the hit to the
     16        character corresponding to the hit interval.
     17        (WebCore::ComplexTextController::advance): If the final offset occurs mid-glyph, advance
     18        by a fraction of the glyph’s total advance.
     19        * platform/graphics/mac/ComplexTextController.h: Added m_characterInCurrentGlyph.
     20
    1212009-10-29  Brian Weinstein  <bweinstein@apple.com>
    222
  • trunk/WebCore/platform/graphics/mac/ComplexTextController.cpp

    r50259 r50301  
    3030#include "TextBreakIterator.h"
    3131
     32using namespace std;
     33
    3234namespace WebCore {
    3335
     
    5759    , m_currentRun(0)
    5860    , m_glyphInCurrentRun(0)
     61    , m_characterInCurrentGlyph(0)
    5962    , m_finalRoundingWidth(0)
    6063    , m_fallbackFonts(fallbackFonts)
     
    8285int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
    8386{
    84     // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
    85     // approximate it by dividing the width of the ligature by the number of characters it encompasses.
    86     // However, Core Text does not expose a low-level API for directly finding
    87     // out how many characters a ligature encompasses (the "attachment count").
    8887    if (h >= m_totalWidth)
    8988        return m_run.ltr() ? m_end : 0;
     
    10099        for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
    101100            CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
    102             if (x <= adjustedAdvance) {
    103                 CFIndex hitIndex = complexTextRun.indexAt(j);
     101            if (x < adjustedAdvance) {
     102                CFIndex hitGlyphStart = complexTextRun.indexAt(j);
     103                CFIndex hitGlyphEnd;
     104                if (m_run.ltr())
     105                    hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : complexTextRun.stringLength());
     106                else
     107                    hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.stringLength());
     108
     109                // FIXME: Instead of dividing the glyph's advance equially between the characters, this
     110                // could use the glyph's "ligature carets". However, there is no Core Text API to get the
     111                // ligature carets.
     112                CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
    104113                int stringLength = complexTextRun.stringLength();
    105114                TextBreakIterator* cursorPositionIterator = cursorMovementIterator(complexTextRun.characters(), stringLength);
     
    120129                    clusterEnd = stringLength;
    121130
    122                 CGFloat clusterWidth = adjustedAdvance;
     131                CGFloat clusterWidth;
    123132                // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
    124133                // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
    125134                // reordering and on font fallback should occur within a CTLine.
    126135                if (clusterEnd - clusterStart > 1) {
     136                    clusterWidth = adjustedAdvance;
    127137                    int firstGlyphBeforeCluster = j - 1;
    128138                    while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
     
    137147                        firstGlyphAfterCluster++;
    138148                    }
     149                } else {
     150                    clusterWidth = adjustedAdvance / (hitGlyphEnd - hitGlyphStart);
     151                    x -=  clusterWidth * (m_run.ltr() ? hitIndex - hitGlyphStart : hitGlyphEnd - hitIndex - 1);
    139152                }
    140153                if (x <= clusterWidth / 2)
     
    253266void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
    254267{
    255     // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"
    256     // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional
    257     // to the offsets into the ligature. However, Core Text does not expose a low-level API for
    258     // directly finding out how many characters a ligature encompasses (the "attachment count").
    259268    if (static_cast<int>(offset) > m_end)
    260269        offset = m_end;
     
    275284        unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
    276285        while (m_glyphInCurrentRun < glyphCount) {
    277             if (complexTextRun.indexAt(g) + complexTextRun.stringLocation() >= m_currentCharacter)
     286            unsigned glyphStartOffset = complexTextRun.indexAt(g);
     287            unsigned glyphEndOffset;
     288            if (ltr)
     289                glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength());
     290            else
     291                glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength());
     292
     293            CGSize adjustedAdvance = m_adjustedAdvances[k];
     294
     295            if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
    278296                return;
    279             CGSize adjustedAdvance = m_adjustedAdvances[k];
    280             if (glyphBuffer)
     297
     298            if (glyphBuffer && !m_characterInCurrentGlyph)
    281299                glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
    282             m_runWidthSoFar += adjustedAdvance.width;
     300
     301            unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
     302            m_characterInCurrentGlyph = min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
     303            // FIXME: Instead of dividing the glyph's advance equially between the characters, this
     304            // could use the glyph's "ligature carets". However, there is no Core Text API to get the
     305            // ligature carets.
     306            m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
     307
     308            if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
     309                return;
     310
    283311            m_numGlyphsSoFar++;
    284312            m_glyphInCurrentRun++;
     313            m_characterInCurrentGlyph = 0;
    285314            if (ltr) {
    286315                g++;
  • trunk/WebCore/platform/graphics/mac/ComplexTextController.h

    r50264 r50301  
    145145    size_t m_currentRun;
    146146    unsigned m_glyphInCurrentRun;
     147    unsigned m_characterInCurrentGlyph;
    147148    float m_finalRoundingWidth;
    148149    float m_padding;
Note: See TracChangeset for help on using the changeset viewer.