Changeset 106547 in webkit


Ignore:
Timestamp:
Feb 2, 2012 5:53:57 AM (12 years ago)
Author:
kenneth@webkit.org
Message:

Make the tap highlighting work for all test cases
https://bugs.webkit.org/show_bug.cgi?id=77626

Reviewed by Simon Hausmann.

Clean up of the current code to make it more generic. Now uses
addFocusRingRects for finding the areas to highlight.

Tested by current manual tests.

  • page/GestureTapHighlighter.cpp:

(WebCore::GestureTapHighlighter::pathForNodeHighlight):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r106545 r106547  
     12012-02-02  Kenneth Rohde Christiansen  <kenneth@webkit.org>
     2
     3        Make the tap highlighting work for all test cases
     4        https://bugs.webkit.org/show_bug.cgi?id=77626
     5
     6        Reviewed by Simon Hausmann.
     7
     8        Clean up of the current code to make it more generic. Now uses
     9        addFocusRingRects for finding the areas to highlight.
     10
     11        Tested by current manual tests.
     12
     13        * page/GestureTapHighlighter.cpp:
     14        (WebCore::GestureTapHighlighter::pathForNodeHighlight):
     15
    1162012-02-02  Mario Sanchez Prada  <msanchez@igalia.com>
    217
  • trunk/Source/WebCore/page/GestureTapHighlighter.cpp

    r106357 r106547  
    8282}
    8383
    84 Path pathForRenderBox(RenderBox* o)
    85 {
    86     ASSERT(o);
    87     const int rounding = 4;
    88 
    89     LayoutRect contentBox;
    90     LayoutRect paddingBox;
    91     LayoutRect borderBox;
    92 
    93     contentBox = o->contentBoxRect();
    94     paddingBox = LayoutRect(
    95             contentBox.x() - o->paddingLeft(),
    96             contentBox.y() - o->paddingTop(),
    97             contentBox.width() + o->paddingLeft() + o->paddingRight(),
    98             contentBox.height() + o->paddingTop() + o->paddingBottom());
    99     borderBox = LayoutRect(
    100             paddingBox.x() - o->borderLeft(),
    101             paddingBox.y() - o->borderTop(),
    102             paddingBox.width() + o->borderLeft() + o->borderRight(),
    103             paddingBox.height() + o->borderTop() + o->borderBottom());
    104 
    105     FloatRect rect(borderBox);
    106     rect.inflate(rounding);
    107 
    108     rect.move(toLayoutSize(ownerFrameToMainFrameOffset(o)));
    109 
    110     Path path;
    111     FloatSize rounded(rounding * 1.8, rounding * 1.8);
    112     path.addRoundedRect(rect, rounded);
    113 
    114     return path;
    115 }
    116 
    117 void addRectWithRoundedCorners(Path& path, const LayoutRect& rect, bool topLeft, bool topRight, bool bottomLeft, bool bottomRight)
    118 {
     84inline bool contains(const LayoutRect& rect, int x)
     85{
     86    return !rect.isEmpty() && x >= rect.x() && x <= rect.maxX();
     87}
     88
     89inline bool strikes(const LayoutRect& a, const LayoutRect& b)
     90{
     91    return !a.isEmpty() && !b.isEmpty()
     92        && a.x() <= b.maxX() && b.x() <= a.maxX()
     93        && a.y() <= b.maxY() && b.y() <= a.maxY();
     94}
     95
     96inline void shiftXEdgesToContainIfStrikes(LayoutRect& rect, const LayoutRect& other)
     97{
     98    int leftSide = rect.x();
     99    int rightSide = rect.maxX();
     100
     101    if (!other.isEmpty() && strikes(rect, other)) {
     102        leftSide = std::min(leftSide, other.x());
     103        rightSide = std::max(rightSide, other.maxX());
     104    }
     105
     106    rect.setX(leftSide);
     107    rect.setWidth(rightSide - leftSide);
     108}
     109
     110inline void addHighlightRect(Path& path, const LayoutRect& rect, const LayoutRect& prev, const LayoutRect& next)
     111{
     112    // The rounding check depends on the rects not intersecting eachother,
     113    // or being contained for that matter.
     114    ASSERT(!rect.intersects(prev));
     115    ASSERT(!rect.intersects(next));
     116
     117    if (rect.isEmpty())
     118        return;
     119
    119120    const int rounding = 4;
    120121
     
    127128
    128129    path.addBeziersForRoundedRect(copy,
    129             topLeft ? rounded : squared, topRight ? rounded : squared,
    130             bottomLeft ? rounded : squared, bottomRight ? rounded : squared);
    131 }
    132 
    133 inline bool contains(LayoutRect rect, int x)
    134 {
    135     return !rect.isEmpty() && x >= rect.x() && x <= rect.maxX();
    136 }
    137 
    138 Path pathForRenderInline(RenderInline* o)
     130            contains(prev, rect.x()) ? squared : rounded,
     131            contains(prev, rect.maxX()) ? squared : rounded,
     132            contains(next, rect.x()) ? squared : rounded,
     133            contains(next, rect.maxX()) ? squared : rounded);
     134}
     135
     136Path pathForRenderer(RenderObject* o)
    139137{
    140138    ASSERT(o);
     
    142140
    143141    Vector<LayoutRect> rects;
    144     o->absoluteRects(rects, /* acc. offset */ ownerFrameToMainFrameOffset(o));
    145 
    146     LayoutRect first = rects.size() ? rects.first() : LayoutRect();
    147     LayoutRect last = rects.size() > 1 ? rects.last() : LayoutRect();
    148     LayoutRect middle;
     142    o->addFocusRingRects(rects, /* acc. offset */ ownerFrameToMainFrameOffset(o));
     143
     144    // The basic idea is to allow up to three different boxes in order to highlight
     145    // text with line breaks more nicer than using a bounding box.
     146
     147    // Merge all center boxes (all but the first and the last).
     148    LayoutRect mid;
    149149    for (int i = 1; i < rects.size() - 1; ++i)
    150         middle.uniteIfNonZero(rects.at(i));
    151 
    152     if (!middle.isEmpty()) {
    153         int leftSide = middle.x();
    154         int rightSide = middle.maxX();
    155 
    156         if (!first.isEmpty()) {
    157             leftSide = std::min(leftSide, first.x());
    158             rightSide = std::max(rightSide, first.maxX());
    159         }
    160         if (!last.isEmpty()) {
    161             leftSide = std::min(leftSide, last.x());
    162             rightSide = std::max(rightSide, last.maxX());
    163         }
    164 
    165         middle.setX(leftSide);
    166         middle.setWidth(rightSide - leftSide);
    167     }
    168 
    169     if (!first.isEmpty()) {
    170         bool roundBottomLeft = !contains(middle, first.x()) && !contains(last, first.x());
    171         bool roundBottomRight = !contains(middle, first.maxX()) && !contains(last, first.maxX());
    172         addRectWithRoundedCorners(path, first, /* roundTopLeft */ true, /* roundTopRight */ true, roundBottomLeft, roundBottomRight);
    173     }
    174 
    175     if (!middle.isEmpty()) {
    176         bool roundTopLeft = !contains(first, middle.x());
    177         bool roundBottomRight = !contains(last, middle.maxX());
    178         addRectWithRoundedCorners(path, middle, roundTopLeft, /* roundTopRight */ false, /* roundBottomLeft */ false, roundBottomRight);
    179     }
    180 
    181     if (!last.isEmpty()) {
    182         bool roundTopLeft = !contains(middle, last.x()) && !contains(first, last.x());
    183         bool roundTopRight = !contains(middle, last.maxX()) && !contains(first, last.maxX());
    184         addRectWithRoundedCorners(path, last, roundTopLeft, roundTopRight, /* roundBottomLeft */ true, /* roundBottomRight */ true);
     150        mid.uniteIfNonZero(rects.at(i));
     151
     152    Vector<LayoutRect> drawableRects;
     153
     154    if (!mid.isEmpty())
     155        drawableRects.append(mid);
     156
     157    // Add the first box, but merge it with the center boxes if it intersects.
     158    if (rects.size() && !rects.first().isEmpty()) {
     159        if (drawableRects.size() && drawableRects.last().intersects(rects.first()))
     160            drawableRects.last().unite(rects.first());
     161        else
     162            drawableRects.prepend(rects.first());
     163    }
     164
     165    // Add the last box, but merge it with the center boxes if it intersects.
     166    if (rects.size() > 1 && !rects.last().isEmpty()) {
     167        if (drawableRects.size() && drawableRects.last().intersects(rects.last()))
     168            drawableRects.last().unite(rects.last());
     169        else
     170            drawableRects.append(rects.last());
     171    }
     172
     173    // Adjust middle to boundaries of first and last.
     174    if (drawableRects.size() == 3) {
     175        LayoutRect& middle = drawableRects.at(1);
     176        shiftXEdgesToContainIfStrikes(middle, drawableRects.at(0));
     177        shiftXEdgesToContainIfStrikes(middle, drawableRects.at(2));
     178    }
     179
     180    for (int i = 0; i < drawableRects.size(); ++i) {
     181        LayoutRect prev = (i - 1) >= 0 ? drawableRects.at(i - 1) : LayoutRect();
     182        LayoutRect next = (i + 1) < drawableRects.size() ? drawableRects.at(i + 1) : LayoutRect();
     183        addHighlightRect(path, drawableRects.at(i), prev, next);
    185184    }
    186185
     
    200199        return path;
    201200
    202     if (renderer->isBox())
    203         path = pathForRenderBox(toRenderBox(renderer));
    204     else
    205         path = pathForRenderInline(toRenderInline(renderer));
    206 
     201    path = pathForRenderer(renderer);
    207202    path.transform(localToAbsoluteTransform(renderer));
     203
    208204    return path;
    209205}
Note: See TracChangeset for help on using the changeset viewer.