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

📄 rendercounter.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
字号:
/** * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderCounter.h"#include "CounterNode.h"#include "Document.h"#include "HTMLNames.h"#include "HTMLOListElement.h"#include "RenderListItem.h"#include "RenderListMarker.h"#include "RenderStyle.h"#include <wtf/StdLibExtras.h>namespace WebCore {using namespace HTMLNames;typedef HashMap<RefPtr<AtomicStringImpl>, CounterNode*> CounterMap;typedef HashMap<const RenderObject*, CounterMap*> CounterMaps;static CounterNode* counter(RenderObject*, const AtomicString& counterName, bool alwaysCreateCounter);static CounterMaps& counterMaps(){    DEFINE_STATIC_LOCAL(CounterMaps, staticCounterMaps, ());    return staticCounterMaps;}static inline RenderObject* previousSiblingOrParent(RenderObject* object){    if (RenderObject* sibling = object->previousSibling())        return sibling;    return object->parent();}static CounterNode* lastDescendant(CounterNode* node){    CounterNode* last = node->lastChild();    if (!last)        return 0;    while (CounterNode* lastChild = last->lastChild())        last = lastChild;    return last;}static CounterNode* previousInPreOrder(CounterNode* node){    CounterNode* previous = node->previousSibling();    if (!previous)        return node->parent();    while (CounterNode* lastChild = previous->lastChild())        previous = lastChild;    return previous;}static bool planCounter(RenderObject* object, const AtomicString& counterName, bool& isReset, int& value){    ASSERT(object);    // Real text nodes don't have their own style so they can't have counters.    // We can't even look at their styles or we'll see extra resets and increments!    if (object->isText() && !object->isBR())        return false;    RenderStyle* style = object->style();    ASSERT(style);    if (const CounterDirectiveMap* directivesMap = style->counterDirectives()) {        CounterDirectives directives = directivesMap->get(counterName.impl());        if (directives.m_reset) {            value = directives.m_resetValue;            if (directives.m_increment)                value += directives.m_incrementValue;            isReset = true;            return true;        }        if (directives.m_increment) {            value = directives.m_incrementValue;            isReset = false;            return true;        }    }    if (counterName == "list-item") {        if (object->isListItem()) {            if (static_cast<RenderListItem*>(object)->hasExplicitValue()) {                value = static_cast<RenderListItem*>(object)->explicitValue();                isReset = true;                return true;            }            value = 1;            isReset = false;            return true;        }        if (Node* e = object->node()) {            if (e->hasTagName(olTag)) {                value = static_cast<HTMLOListElement*>(e)->start();                isReset = true;                return true;            }            if (e->hasTagName(ulTag) || e->hasTagName(menuTag) || e->hasTagName(dirTag)) {                value = 0;                isReset = true;                return true;            }        }    }    return false;}static bool findPlaceForCounter(RenderObject* object, const AtomicString& counterName,    bool isReset, CounterNode*& parent, CounterNode*& previousSibling){    // Find the appropriate previous sibling for insertion into the parent node    // by searching in render tree order for a child of the counter.    parent = 0;    previousSibling = 0;    RenderObject* resetCandidate = isReset ? object->parent() : previousSiblingOrParent(object);    RenderObject* prevCounterCandidate = object;    CounterNode* candidateCounter = 0;    while ((prevCounterCandidate = prevCounterCandidate->previousInPreOrder())) {        CounterNode* c = counter(prevCounterCandidate, counterName, false);        if (prevCounterCandidate == resetCandidate) {            if (!candidateCounter)                candidateCounter = c;            if (candidateCounter) {                if (candidateCounter->isReset()) {                    parent = candidateCounter;                    previousSibling = 0;                } else {                    parent = candidateCounter->parent();                    previousSibling = candidateCounter;                }                return true;            }            resetCandidate = previousSiblingOrParent(resetCandidate);        } else if (c) {            if (c->isReset())                candidateCounter = 0;            else if (!candidateCounter)                candidateCounter = c;        }    }    return false;}static CounterNode* counter(RenderObject* object, const AtomicString& counterName, bool alwaysCreateCounter){    ASSERT(object);    if (object->m_hasCounterNodeMap)        if (CounterMap* nodeMap = counterMaps().get(object))            if (CounterNode* node = nodeMap->get(counterName.impl()))                return node;    bool isReset = false;    int value = 0;    if (!planCounter(object, counterName, isReset, value) && !alwaysCreateCounter)        return 0;    CounterNode* newParent = 0;    CounterNode* newPreviousSibling = 0;    CounterNode* newNode;    if (findPlaceForCounter(object, counterName, isReset, newParent, newPreviousSibling)) {        newNode = new CounterNode(object, isReset, value);        newParent->insertAfter(newNode, newPreviousSibling);    } else {        // Make a reset node for counters that aren't inside an existing reset node.        newNode = new CounterNode(object, true, value);    }    CounterMap* nodeMap;    if (object->m_hasCounterNodeMap)        nodeMap = counterMaps().get(object);    else {        nodeMap = new CounterMap;        counterMaps().set(object, nodeMap);        object->m_hasCounterNodeMap = true;    }    nodeMap->set(counterName.impl(), newNode);    return newNode;}RenderCounter::RenderCounter(Document* node, const CounterContent& counter)    : RenderText(node, StringImpl::empty())    , m_counter(counter)    , m_counterNode(0){}const char* RenderCounter::renderName() const{    return "RenderCounter";}bool RenderCounter::isCounter() const{    return true;}PassRefPtr<StringImpl> RenderCounter::originalText() const{    if (!parent())        return 0;    if (!m_counterNode)        m_counterNode = counter(parent(), m_counter.identifier(), true);    CounterNode* child = m_counterNode;    int value = child->isReset() ? child->value() : child->countInParent();    String text = listMarkerText(m_counter.listStyle(), value);    if (!m_counter.separator().isNull()) {        if (!child->isReset())            child = child->parent();        while (CounterNode* parent = child->parent()) {            text = listMarkerText(m_counter.listStyle(), child->countInParent())                + m_counter.separator() + text;            child = parent;        }    }    return text.impl();}void RenderCounter::calcPrefWidths(int lead){    setTextInternal(originalText());    RenderText::calcPrefWidths(lead);}void RenderCounter::invalidate(){    m_counterNode = 0;    setNeedsLayoutAndPrefWidthsRecalc();}static void destroyCounterNodeChildren(AtomicStringImpl* identifier, CounterNode* node){    CounterNode* previous;    for (CounterNode* child = lastDescendant(node); child && child != node; child = previous) {        previous = previousInPreOrder(child);        child->parent()->removeChild(child);        ASSERT(counterMaps().get(child->renderer())->get(identifier) == child);        counterMaps().get(child->renderer())->remove(identifier);        if (!child->renderer()->documentBeingDestroyed()) {            RenderObjectChildList* children = child->renderer()->virtualChildren();            if (children)                children->invalidateCounters(child->renderer());        }        delete child;    }}void RenderCounter::destroyCounterNodes(RenderObject* object){    CounterMaps& maps = counterMaps();    CounterMap* map = maps.get(object);    if (!map)        return;    maps.remove(object);    CounterMap::const_iterator end = map->end();    for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {        CounterNode* node = it->second;        destroyCounterNodeChildren(it->first.get(), node);        if (CounterNode* parent = node->parent())            parent->removeChild(node);        delete node;    }    delete map;}} // namespace WebCore

⌨️ 快捷键说明

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