⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 render_layer.cpp

📁 konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版本源码包.
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        // Now restore our clip.        restoreClip(p, paintDirtyRect, clipRectToApply);    }    // Now walk the sorted list of children with positive z-indices.    if (m_posZOrderList) {        uint count = m_posZOrderList->count();        for (uint i = 0; i < count; i++) {            RenderLayer* child = m_posZOrderList->at(i);            child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);        }    }#ifdef BOX_DEBUG    {        int ax=0;        int ay=0;        renderer()->absolutePosition( ax, ay );        p->setPen(QPen(QColor("yellow"), 1, Qt::DotLine));        p->setBrush( Qt::NoBrush );        p->drawRect(ax, ay, width(), height());    }#endif#ifdef APPLE_CHANGES    // End our transparency layer    if (isTransparent())        p->endTransparencyLayer();#endif}bool RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y){#ifdef APPLE_CHANGES    // Clear our our scrollbar variable    RenderLayer::gScrollBar = 0;#endif    int stx = m_x;    int sty = m_y;#ifdef __GNUC__#warning HACK#endif    if (renderer()->isCanvas()) {        stx += static_cast<RenderCanvas*>(renderer())->view()->contentsX();        sty += static_cast<RenderCanvas*>(renderer())->view()->contentsY();    }    QRect damageRect(stx,sty, width(), height());    RenderLayer* insideLayer = nodeAtPointForLayer(this, info, x, y, damageRect);    // Now determine if the result is inside an anchor.    DOM::NodeImpl* node = info.innerNode();    while (node) {        if (node->hasAnchor() && !info.URLElement())            info.setURLElement(node);        node = node->parentNode();    }    // Next set up the correct :hover/:active state along the new chain.    updateHoverActiveState(info);    // Now return whether we were inside this layer (this will always be true for the root    // layer).    return insideLayer;}RenderLayer* RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,                                 int xMousePos, int yMousePos, const QRect& hitTestRect){    // Calculate the clip rects we should use.    QRect layerBounds, bgRect, fgRect;    calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);    // Ensure our z-order lists are up-to-date.    updateZOrderLists();    // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,    // we are done and can return it.    RenderLayer* insideLayer = 0;    // Begin by walking our list of positive layers from highest z-index down to the lowest    // z-index.    if (m_posZOrderList) {        uint count = m_posZOrderList->count();        for (int i = count-1; i >= 0; i--) {            RenderLayer* child = m_posZOrderList->at(i);            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);            if (insideLayer)                return insideLayer;        }    }    // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.    if (containsPoint(xMousePos, yMousePos, fgRect) &&        renderer()->nodeAtPoint(info, xMousePos, yMousePos,                                layerBounds.x() - renderer()->xPos(),                                layerBounds.y() - renderer()->yPos(),                                HitTestChildrenOnly)) {	if (info.innerNode() != m_object->element())	    return this;    }    // Now check our negative z-index children.    if (m_negZOrderList) {        uint count = m_negZOrderList->count();        for (int i = count-1; i >= 0; i--) {            RenderLayer* child = m_negZOrderList->at(i);            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);            if (insideLayer)                return insideLayer;        }    }    // Next we want to see if the mouse pos is inside this layer but not any of its children.    if (containsPoint(xMousePos, yMousePos, bgRect) &&        renderer()->nodeAtPoint(info, xMousePos, yMousePos,                                layerBounds.x() - renderer()->xPos(),                                layerBounds.y() - renderer()->yPos(),                                HitTestSelfOnly))        return this;    // No luck.    return 0;}void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, QRect& overflowClipRect,                                     QRect& posClipRect, QRect& fixedClipRect){    if (parent())        parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);    switch (m_object->style()->position()) {      // A fixed object is essentially the root of its containing block hierarchy, so when      // we encounter such an object, we reset our clip rects to the fixedClipRect.      case FIXED:         posClipRect = fixedClipRect;         overflowClipRect = fixedClipRect;        break;      case ABSOLUTE:        overflowClipRect = posClipRect;        break;      case RELATIVE:        posClipRect = overflowClipRect;        break;      default:        break;    }    // Update the clip rects that will be passed to child layers.    if (m_object->hasOverflowClip() || m_object->hasClip()) {        // This layer establishes a clip of some kind.        int x = 0;        int y = 0;        convertToLayerCoords(rootLayer, x, y);        if (m_object->hasOverflowClip()) {            QRect newOverflowClip = m_object->getOverflowClipRect(x,y);            overflowClipRect  = newOverflowClip.intersect(overflowClipRect);            if (m_object->isPositioned() || m_object->isRelPositioned())                posClipRect = newOverflowClip.intersect(posClipRect);        }        if (m_object->hasClip()) {            QRect newPosClip = m_object->getClipRect(x,y);            posClipRect = posClipRect.intersect(newPosClip);            overflowClipRect = overflowClipRect.intersect(newPosClip);            fixedClipRect = fixedClipRect.intersect(newPosClip);        }    }}void RenderLayer::calculateRects(const RenderLayer* rootLayer, const QRect& paintDirtyRect, QRect& layerBounds,                                 QRect& backgroundRect, QRect& foregroundRect){    QRect overflowClipRect = paintDirtyRect;    QRect posClipRect = paintDirtyRect;    QRect fixedClipRect = paintDirtyRect;    if (parent())        parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);    int x = 0;    int y = 0;    convertToLayerCoords(rootLayer, x, y);    layerBounds = QRect(x,y,width(),height());    backgroundRect = m_object->style()->position() == FIXED ? fixedClipRect :        (m_object->isPositioned() ? posClipRect : overflowClipRect);    foregroundRect = backgroundRect;    // Update the clip rects that will be passed to child layers.    if (m_object->hasOverflowClip() || m_object->hasClip()) {        // This layer establishes a clip of some kind.        if (m_object->hasOverflowClip())            foregroundRect = foregroundRect.intersect(m_object->getOverflowClipRect(x,y));        if (m_object->hasClip()) {            // Clip applies to *us* as well, so go ahead and update the damageRect.            QRect newPosClip = m_object->getClipRect(x,y);            backgroundRect = backgroundRect.intersect(newPosClip);            foregroundRect = foregroundRect.intersect(newPosClip);        }        // If we establish a clip at all, then go ahead and make sure our background        // rect is intersected with our layer's bounds.        backgroundRect = backgroundRect.intersect(layerBounds);    }}bool RenderLayer::intersectsDamageRect(const QRect& layerBounds, const QRect& damageRect) const{    return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||            (renderer()->hasOverhangingFloats() && !renderer()->hasOverflowClip()) ||            (renderer()->isInline() && !renderer()->isReplaced()) ||            layerBounds.intersects(damageRect));}bool RenderLayer::containsPoint(int x, int y, const QRect& damageRect) const{    return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||            renderer()->hasOverhangingFloats() ||            (renderer()->isInline() && !renderer()->isReplaced()) ||            damageRect.contains(x, y));}// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated// content (and perhaps XBL).  That's why it uses the render tree and not the DOM tree.static RenderObject* hoverAncestor(RenderObject* obj){    return (!obj->isInline() && obj->continuation()) ? obj->continuation() : obj->parent();}static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2){    if (!obj1 || !obj2)        return 0;    for (RenderObject* currObj1 = obj1; currObj1; currObj1 = hoverAncestor(currObj1))        for (RenderObject* currObj2 = obj2; currObj2; currObj2 = hoverAncestor(currObj2))            if (currObj1 == currObj2)                return currObj1;    return 0;}void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info){    // We don't update :hover/:active state when the info is marked as readonly.    if (info.readonly())        return;    // Check to see if the hovered node has changed.  If not, then we don't need to    // do anything.  An exception is if we just went from :hover into :hover:active,    // in which case we need to update to get the new :active state.    DOM::NodeImpl *e = m_object->element();    DOM::DocumentImpl *doc = e ? e->getDocument() : 0;    if (!doc)	return;    DOM::NodeImpl* oldHoverNode = doc->hoverNode();    DOM::NodeImpl* newHoverNode = info.innerNode();        if (oldHoverNode == newHoverNode && (!oldHoverNode || oldHoverNode->active() == info.active()))        return;    // Update our current hover node.    doc->setHoverNode(newHoverNode);    // We have two different objects.  Fetch their renderers.    RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;    RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;    // Locate the common ancestor render object for the two renderers.    RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);    // The old hover path only needs to be cleared up to (and not including) the common ancestor;    for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = hoverAncestor(curr)) {        curr->setMouseInside(false);        if (curr->element()) {            bool oldActive = curr->element()->active();            curr->element()->NodeImpl::setActive(false);            if (!curr->isText() && (curr->style()->affectedByHoverRules() ||                 (curr->style()->affectedByActiveRules() && oldActive)))                curr->element()->setChanged();        }    }    // Now set the hover state for our new object up to the root.    for (RenderObject* curr = newHoverObj; curr; curr = hoverAncestor(curr)) {        bool oldInside = curr->mouseInside();        curr->setMouseInside(true);        if (curr->element()) {            bool oldActive = curr->element()->active();            curr->element()->NodeImpl::setActive(info.active());            if (!curr->isText() && (curr->style()->affectedByHoverRules() && !oldInside) ||                 (curr->style()->affectedByActiveRules() && oldActive != info.active())) {                curr->element()->setChanged();            }        }    }}// Sort the buffer from lowest z-index to highest.  The common scenario will have// most z-indices equal, so we optimize for that case (i.e., the list will be mostly// sorted already).static void sortByZOrder(QPtrVector<RenderLayer>* buffer,                         QPtrVector<RenderLayer>* mergeBuffer,                         uint start, uint end){    if (start >= end)        return; // Sanity check.    if (end - start <= 6) {        // Apply a bubble sort for smaller lists.        for (uint i = end-1; i > start; i--) {            bool sorted = true;            for (uint j = start; j < i; j++) {                RenderLayer* elt = buffer->at(j);                RenderLayer* elt2 = buffer->at(j+1);                if (elt->zIndex() > elt2->zIndex()) {                    sorted = false;                    buffer->insert(j, elt2);                    buffer->insert(j+1, elt);                }            }            if (sorted)                return;        }    }    else {        // Peform a merge sort for larger lists.        uint mid = (start+end)/2;        sortByZOrder(buffer, mergeBuffer, start, mid);        sortByZOrder(buffer, mergeBuffer, mid, end);        RenderLayer* elt = buffer->at(mid-1);        RenderLayer* elt2 = buffer->at(mid);        // Handle the fast common case (of equal z-indices).  The list may already        // be completely sorted.        if (elt->zIndex() <= elt2->zIndex())            return;        // We have to merge sort.  Ensure our merge buffer is big enough to hold        // all the items.        mergeBuffer->resize(end - start);        uint i1 = start;        uint i2 = mid;        elt = buffer->at(i1);        elt2 = buffer->at(i2);        while (i1 < mid || i2 < end) {            if (i1 < mid && (i2 == end || elt->zIndex() <= elt2->zIndex())) {                mergeBuffer->insert(mergeBuffer->count(), elt);                i1++;                if (i1 < mid)                    elt = buffer->at(i1);            }            else {                mergeBuffer->insert(mergeBuffer->count(), elt2);                i2++;                if (i2 < end)                    elt2 = buffer->at(i2);            }        }        for (uint i = start; i < end; i++)            buffer->insert(i, mergeBuffer->at(i-start));        mergeBuffer->clear();    }}void RenderLayer::dirtyZOrderLists(){    if (m_posZOrderList)        m_posZOrderList->clear();    if (m_negZOrderList)        m_negZOrderList->clear();    m_zOrderListsDirty = true;}void RenderLayer::updateZOrderLists(){    if (!isStackingContext() || !m_zOrderListsDirty)        return;    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())        child->collectLayers(m_posZOrderList, m_negZOrderList);    // Sort the two lists.    if (m_posZOrderList) {        QPtrVector<RenderLayer> mergeBuffer;        sortByZOrder(m_posZOrderList, &mergeBuffer, 0, m_posZOrderList->count());    }    if (m_negZOrderList) {        QPtrVector<RenderLayer> mergeBuffer;        sortByZOrder(m_negZOrderList, &mergeBuffer, 0, m_negZOrderList->count());    }    m_zOrderListsDirty = false;}void RenderLayer::collectLayers(QPtrVector<RenderLayer>*& posBuffer, QPtrVector<RenderLayer>*& negBuffer){    // FIXME: A child render object or layer could override visibility.  Don't remove this    // optimization though until RenderObject's nodeAtPoint is patched to understand what to do    // when visibility is overridden by a child.    if (renderer()->style()->visibility() != VISIBLE)        return;    // Determine which buffer the child should be in.    QPtrVector<RenderLayer>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;    // Create the buffer if it doesn't exist yet.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -