Пример #1
0
void distanceDataForNode(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate)
{
    if (areElementsOnSameLine(current, candidate)) {
        if ((direction == FocusDirectionUp && current.rect.y() > candidate.rect.y()) || (direction == FocusDirectionDown && candidate.rect.y() > current.rect.y())) {
            candidate.distance = 0;
            candidate.alignment = Full;
            return;
        }
    }

    IntRect nodeRect = candidate.rect;
    IntRect currentRect = current.rect;
    deflateIfOverlapped(currentRect, nodeRect);

    if (!isRectInDirection(direction, currentRect, nodeRect))
        return;

    IntPoint exitPoint;
    IntPoint entryPoint;
    int sameAxisDistance = 0;
    int otherAxisDistance = 0;
    entryAndExitPointsForDirection(direction, currentRect, nodeRect, exitPoint, entryPoint);

    switch (direction) {
    case FocusDirectionLeft:
        sameAxisDistance = exitPoint.x() - entryPoint.x();
        otherAxisDistance = abs(exitPoint.y() - entryPoint.y());
        break;
    case FocusDirectionUp:
        sameAxisDistance = exitPoint.y() - entryPoint.y();
        otherAxisDistance = abs(exitPoint.x() - entryPoint.x());
        break;
    case FocusDirectionRight:
        sameAxisDistance = entryPoint.x() - exitPoint.x();
        otherAxisDistance = abs(entryPoint.y() - exitPoint.y());
        break;
    case FocusDirectionDown:
        sameAxisDistance = entryPoint.y() - exitPoint.y();
        otherAxisDistance = abs(entryPoint.x() - exitPoint.x());
        break;
    default:
        ASSERT_NOT_REACHED();
        return;
    }

    int x = (entryPoint.x() - exitPoint.x()) * (entryPoint.x() - exitPoint.x());
    int y = (entryPoint.y() - exitPoint.y()) * (entryPoint.y() - exitPoint.y());

    float euclidianDistance = sqrt((x + y) * 1.0f);

    // Loosely based on http://www.w3.org/TR/WICD/#focus-handling
    // df = dotDist + dx + dy + 2 * (xdisplacement + ydisplacement) - sqrt(Overlap)

    float distance = euclidianDistance + sameAxisDistance + 2 * otherAxisDistance;
    candidate.distance = roundf(distance);
    IntSize viewSize = candidate.visibleNode->document()->page()->mainFrame()->view()->visibleContentRect().size();
    candidate.alignment = alignmentForRects(direction, currentRect, nodeRect, viewSize);
}
Пример #2
0
void distanceDataForNode(FocusDirection direction, Node* start, FocusCandidate& candidate)
{
    RenderObject* startRender = start->renderer();
    if (!startRender) {
        candidate.distance = maxDistance();
        return;
    }

    RenderObject* destRender = candidate.node->renderer();
    if (!destRender) {
        candidate.distance = maxDistance();
        return;
    }

    IntRect curRect = renderRectRelativeToRootDocument(startRender);
    IntRect targetRect  = renderRectRelativeToRootDocument(destRender);

    // The bounding rectangle of two consecutive nodes can overlap. In such cases,
    // deflate both.
    deflateIfOverlapped(curRect, targetRect);

    // If empty rects or negative width or height, bail out.
    if (curRect.isEmpty() || targetRect.isEmpty()
     || targetRect.width() <= 0 || targetRect.height() <= 0) {
        candidate.distance = maxDistance();
        return;
    }

    // Negative coordinates can be used if node is scrolled up offscreen.
    if (!checkNegativeCoordsForNode(start, curRect)) {
        candidate.distance = maxDistance();
        return;
    }

    if (!checkNegativeCoordsForNode(candidate.node, targetRect)) {
        candidate.distance = maxDistance();
        return;
    }

    if (!isRectInDirection(direction, curRect, targetRect)) {
        candidate.distance = maxDistance();
        return;
    }

    // The distance between two nodes is not to be considered alone when evaluating/looking
    // for the best focus candidate node. Alignment of rects can be also a good point to be
    // considered in order to make the algorithm to behavior in a more intuitive way.
    candidate.alignment = alignmentForRects(direction, curRect, targetRect);
    candidate.distance = spatialDistance(direction, curRect, targetRect);
}