?? cssstyleselector.cpp
字號:
while (n) {
if (canShareStyleWithElement(n))
return n->renderer()->style();
if (count++ == siblingThreshold)
return 0;
for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
}
}
return 0;
}
RenderStyle* CSSStyleSelector::styleForElement(ElementImpl* e, RenderStyle* defaultParent, bool allowSharing)
{
#if NOKIA_CHANGES
if (!e->getDocument()->haveStylesheetsLoaded() && !e->getDocument()->fastDisplayMode()) {
#else
if (!e->getDocument()->haveStylesheetsLoaded()) {
#endif
if (!styleNotYetAvailable) {
styleNotYetAvailable = ::new RenderStyle();
styleNotYetAvailable->setDisplay(NONE);
styleNotYetAvailable->ref();
}
return styleNotYetAvailable;
}
initElementAndPseudoState(e);
if (allowSharing) {
style = locateSharedStyle();
#ifdef STYLE_SHARING_STATS
fraction += style != 0;
total++;
printf("Sharing %d out of %d\n", fraction, total);
#endif
if (style)
return style;
}
initForStyleResolve(e, defaultParent);
style = new (e->getDocument()->renderArena()) RenderStyle();
if (parentStyle)
style->inheritFrom(parentStyle);
else
parentStyle = style;
// 1. First we match rules from the user agent sheet.
int firstUARule = -1, lastUARule = -1;
matchRules(defaultStyle, firstUARule, lastUARule);
// 2. In quirks mode, we match rules from the quirks user agent sheet.
if (!strictParsing)
matchRules(defaultQuirksStyle, firstUARule, lastUARule);
// 3. If our medium is print, then we match rules from the print sheet.
if (m_medium == "print")
matchRules(defaultPrintStyle, firstUARule, lastUARule);
// 4. Now we check user sheet rules.
int firstUserRule = -1, lastUserRule = -1;
matchRules(m_userStyle, firstUserRule, lastUserRule);
// 5. Now check author rules, beginning first with presentational attributes
// mapped from HTML.
int firstAuthorRule = -1, lastAuthorRule = -1;
if (htmlElement) {
// Ask if the HTML element has mapped attributes.
if (htmlElement->hasMappedAttributes()) {
// Walk our attribute list and add in each decl.
const HTMLNamedAttrMapImpl* map = htmlElement->htmlAttributes();
for (uint i = 0; i < map->length(); i++) {
HTMLAttributeImpl* attr = map->attributeItem(i);
if (attr->decl()) {
if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
lastAuthorRule = m_matchedDeclCount;
addMatchedDeclaration(attr->decl());
}
}
}
// Now we check additional mapped declarations.
// Tables and table cells share an additional mapped rule that must be applied
// after all attributes, since their mapped style depends on the values of multiple attributes.
CSSMutableStyleDeclarationImpl* attributeDecl = htmlElement->additionalAttributeStyleDecl();
if (attributeDecl) {
if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
lastAuthorRule = m_matchedDeclCount;
addMatchedDeclaration(attributeDecl);
}
}
// 6. Check the rules in author sheets next.
matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
// 7. Now check our inline style attribute.
if (htmlElement) {
CSSMutableStyleDeclarationImpl* inlineDecl = htmlElement->inlineStyleDecl();
if (inlineDecl) {
if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
lastAuthorRule = m_matchedDeclCount;
addMatchedDeclaration(inlineDecl);
}
}
// Now we have all of the matched rules in the appropriate order. Walk the rules and apply
// high-priority properties first, i.e., those properties that other properties depend on.
// The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
// and (4) normal important.
applyDeclarations(true, false, 0, m_matchedDeclCount-1);
applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
applyDeclarations(true, true, firstUserRule, lastUserRule);
applyDeclarations(true, true, firstUARule, lastUARule);
// If our font got dirtied, go ahead and update it now.
if (fontDirty) {
checkForTextSizeAdjust();
checkForGenericFamilyChange(style, parentStyle);
style->htmlFont().update(paintDeviceMetrics);
fontDirty = false;
}
// Now do the normal priority properties.
applyDeclarations(false, false, 0, m_matchedDeclCount-1);
applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
applyDeclarations(false, true, firstUserRule, lastUserRule);
applyDeclarations(false, true, firstUARule, lastUARule);
// If our font got dirtied by one of the non-essential font props,
// go ahead and update it a second time.
if (fontDirty) {
checkForTextSizeAdjust();
checkForGenericFamilyChange(style, parentStyle);
style->htmlFont().update(paintDeviceMetrics);
fontDirty = false;
}
// Clean up our style object's display and text decorations (among other fixups).
adjustRenderStyle(style, e);
// If we are a link, cache the determined pseudo-state.
if (e->hasAnchor())
style->setPseudoState(pseudoState);
// Now return the style.
return style;
}
RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo,
ElementImpl* e, RenderStyle* parentStyle)
{
if (!e)
return 0;
initElementAndPseudoState(e);
initForStyleResolve(e, parentStyle);
pseudoStyle = pseudo;
// Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
// those rules.
// Check UA, user and author rules.
int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
matchRules(defaultStyle, firstUARule, lastUARule);
matchRules(m_userStyle, firstUserRule, lastUserRule);
matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
if (m_matchedDeclCount == 0)
return 0;
style = new (e->getDocument()->renderArena()) RenderStyle();
if (parentStyle)
style->inheritFrom(parentStyle);
else
parentStyle = style;
style->noninherited_flags._styleType = pseudoStyle;
// High-priority properties.
applyDeclarations(true, false, 0, m_matchedDeclCount-1);
applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
applyDeclarations(true, true, firstUserRule, lastUserRule);
applyDeclarations(true, true, firstUARule, lastUARule);
// If our font got dirtied, go ahead and update it now.
if (fontDirty) {
checkForTextSizeAdjust();
checkForGenericFamilyChange(style, parentStyle);
style->htmlFont().update(paintDeviceMetrics);
fontDirty = false;
}
// Now do the normal priority properties.
applyDeclarations(false, false, 0, m_matchedDeclCount-1);
applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
applyDeclarations(false, true, firstUserRule, lastUserRule);
applyDeclarations(false, true, firstUARule, lastUARule);
// If our font got dirtied by one of the non-essential font props,
// go ahead and update it a second time.
if (fontDirty) {
checkForTextSizeAdjust();
checkForGenericFamilyChange(style, parentStyle);
style->htmlFont().update(paintDeviceMetrics);
fontDirty = false;
}
// Clean up our style object's display and text decorations (among other fixups).
adjustRenderStyle(style, 0);
// Now return the style.
return style;
}
void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e)
{
// Cache our original display.
style->setOriginalDisplay(style->display());
if (style->display() != NONE) {
// If we have a <td> that specifies a float property, in quirks mode we just drop the float
// property.
// Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
// these tags to retain their display types.
if (!strictParsing && e) {
if (e->id() == ID_TD) {
style->setDisplay(TABLE_CELL);
style->setFloating(FNONE);
}
else if (e->id() == ID_TABLE)
style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
}
// Frames and framesets never honor position:relative or position:absolute. This is necessary to
// fix a crash where a site tries to position these objects. They also never honor display.
if (e && (e->id() == ID_FRAME || e->id() == ID_FRAMESET)) {
style->setPosition(STATIC);
style->setDisplay(BLOCK);
}
// Table headers with a text-align of auto will change the text-align to center.
if (e && e->id() == ID_TH && style->textAlign() == TAAUTO)
style->setTextAlign(CENTER);
// Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
// position or float an inline, compact, or run-in. Cache the original display, since it
// may be needed for positioned elements that have to compute their static normal flow
// positions. We also force inline-level roots to be block-level.
if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
(style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE ||
(e && e->getDocument()->documentElement() == e))) {
if (style->display() == INLINE_TABLE)
style->setDisplay(TABLE);
else if (style->display() == INLINE_BOX)
style->setDisplay(BOX);
else if (style->display() == LIST_ITEM) {
// It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
// but only in quirks mode.
if (!strictParsing && style->floating() != FNONE)
style->setDisplay(BLOCK);
}
else
style->setDisplay(BLOCK);
}
// After performing the display mutation, check table rows. We do not honor position:relative on
// table rows. This has been established in CSS2.1 (and caused a crash in containingBlock() on
// some sites).
if (style->display() == TABLE_ROW && style->position() == RELATIVE)
style->setPosition(STATIC);
}
// Make sure our z-index value is only applied if the object is positioned,
// relatively positioned, or transparent.
if (style->position() == STATIC && style->opacity() == 1.0f) {
if (e && e->getDocument()->documentElement() == e)
style->setZIndex(0); // The root has a z-index of 0 if not positioned or transparent.
else
style->setHasAutoZIndex(); // Everyone else gets an auto z-index.
}
// Auto z-index becomes 0 for transparent objects. This prevents cases where
// objects that should be blended as a single unit end up with a non-transparent object
// wedged in between them.
if (style->opacity() < 1.0f && style->hasAutoZIndex())
style->setZIndex(0);
// Finally update our text decorations in effect, but don't allow text-decoration to percolate through
// tables, inline blocks, inline tables, or run-ins.
if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
|| style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
style->setTextDecorationsInEffect(style->textDecoration());
else
style->addToTextDecorationsInEffect(style->textDecoration());
// Cull out any useless layers and also repeat patterns into additional layers.
style->adjustBackgroundLayers();
// Only use slow repaints if we actually have a background image.
// FIXME: We only need to invalidate the fixed regions when scrolling. It's total overkill to
// prevent the entire view from blitting on a scroll.
if (style->hasFixedBackgroundImage() && view)
view->useSlowRepaints();
}
static bool subject;
bool CSSStyleSelector::checkSelector(CSSSelector* sel, ElementImpl *e)
{
dynamicPseudo = RenderStyle::NOPSEUDO;
NodeImpl *n = e;
// we have the subject part of the selector
subject = true;
// We track whether or not the rule contains only :hover and :active in a simple selector. If
// so, we can't allow that to apply to every element on the page. We assume the author intended
// to apply the rules only to links.
bool onlyHoverActive = (sel->tag == anyQName &&
(sel->match == CSSSelector::Pseudo &&
(sel->pseudoType() == CSSSelector::PseudoHover ||
sel->pseudoType() == CSSSelector::PseudoActive)));
bool affectedByHover = style ? style->affectedByHoverRules() : false;
bool affectedByActive = style ? style->affectedByActiveRules() : false;
bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
// first selector has to match
if (!checkOneSelector(sel, e)) return false;
// check the subselectors
CSSSelector::Relation relation = sel->relation;
while((sel = sel->tagHistory))
{
if (!n->isElementNode()) return false;
if (relation != CSSSelector::SubSelector) {
subject = false;
if (havePseudo && dynamicPseudo != pseudoStyle)
return false;
}
switch(relation)
{
case CSSSelector::Descendant:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -