OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Peter Kelly (pmk@post.com) | 4 * (C) 2001 Peter Kelly (pmk@post.com) |
5 * (C) 2001 Dirk Mueller (mueller@kde.org) | 5 * (C) 2001 Dirk Mueller (mueller@kde.org) |
6 * (C) 2007 David Smith (catfish.man@gmail.com) | 6 * (C) 2007 David Smith (catfish.man@gmail.com) |
7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. | 7 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. |
8 * (C) 2007 Eric Seidel (eric@webkit.org) | 8 * (C) 2007 Eric Seidel (eric@webkit.org) |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 #include "core/html/HTMLTableRowsCollection.h" | 96 #include "core/html/HTMLTableRowsCollection.h" |
97 #include "core/html/HTMLTemplateElement.h" | 97 #include "core/html/HTMLTemplateElement.h" |
98 #include "core/html/parser/HTMLParserIdioms.h" | 98 #include "core/html/parser/HTMLParserIdioms.h" |
99 #include "core/inspector/InspectorInstrumentation.h" | 99 #include "core/inspector/InspectorInstrumentation.h" |
100 #include "core/page/Chrome.h" | 100 #include "core/page/Chrome.h" |
101 #include "core/page/ChromeClient.h" | 101 #include "core/page/ChromeClient.h" |
102 #include "core/page/FocusController.h" | 102 #include "core/page/FocusController.h" |
103 #include "core/page/Page.h" | 103 #include "core/page/Page.h" |
104 #include "core/page/PointerLockController.h" | 104 #include "core/page/PointerLockController.h" |
105 #include "core/rendering/RenderLayer.h" | 105 #include "core/rendering/RenderLayer.h" |
106 #include "core/rendering/RenderTextFragment.h" | |
106 #include "core/rendering/RenderView.h" | 107 #include "core/rendering/RenderView.h" |
107 #include "core/rendering/compositing/RenderLayerCompositor.h" | 108 #include "core/rendering/compositing/RenderLayerCompositor.h" |
108 #include "core/svg/SVGDocumentExtensions.h" | 109 #include "core/svg/SVGDocumentExtensions.h" |
109 #include "core/svg/SVGElement.h" | 110 #include "core/svg/SVGElement.h" |
110 #include "platform/EventDispatchForbiddenScope.h" | 111 #include "platform/EventDispatchForbiddenScope.h" |
111 #include "platform/RuntimeEnabledFeatures.h" | 112 #include "platform/RuntimeEnabledFeatures.h" |
112 #include "platform/UserGestureIndicator.h" | 113 #include "platform/UserGestureIndicator.h" |
113 #include "platform/scroll/ScrollableArea.h" | 114 #include "platform/scroll/ScrollableArea.h" |
114 #include "wtf/BitVector.h" | 115 #include "wtf/BitVector.h" |
115 #include "wtf/HashFunctions.h" | 116 #include "wtf/HashFunctions.h" |
116 #include "wtf/text/CString.h" | 117 #include "wtf/text/CString.h" |
117 #include "wtf/text/StringBuilder.h" | 118 #include "wtf/text/StringBuilder.h" |
118 #include "wtf/text/TextPosition.h" | 119 #include "wtf/text/TextPosition.h" |
120 #include "wtf/unicode/icu/UnicodeIcu.h" | |
119 | 121 |
120 namespace blink { | 122 namespace blink { |
121 | 123 |
122 using namespace HTMLNames; | 124 using namespace HTMLNames; |
123 using namespace XMLNames; | 125 using namespace XMLNames; |
124 | 126 |
127 using namespace WTF; | |
128 using namespace Unicode; | |
129 | |
125 typedef WillBeHeapVector<RefPtrWillBeMember<Attr> > AttrNodeList; | 130 typedef WillBeHeapVector<RefPtrWillBeMember<Attr> > AttrNodeList; |
126 | 131 |
127 static Attr* findAttrNodeInList(const AttrNodeList& attrNodeList, const Qualifie dName& name) | 132 static Attr* findAttrNodeInList(const AttrNodeList& attrNodeList, const Qualifie dName& name) |
128 { | 133 { |
129 AttrNodeList::const_iterator end = attrNodeList.end(); | 134 AttrNodeList::const_iterator end = attrNodeList.end(); |
130 for (AttrNodeList::const_iterator it = attrNodeList.begin(); it != end; ++it ) { | 135 for (AttrNodeList::const_iterator it = attrNodeList.begin(); it != end; ++it ) { |
131 if ((*it)->qualifiedName() == name) | 136 if ((*it)->qualifiedName() == name) |
132 return it->get(); | 137 return it->get(); |
133 } | 138 } |
134 return 0; | 139 return 0; |
(...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1339 | 1344 |
1340 // When a shadow root exists, it does the work of attaching the children. | 1345 // When a shadow root exists, it does the work of attaching the children. |
1341 if (ElementShadow* shadow = this->shadow()) | 1346 if (ElementShadow* shadow = this->shadow()) |
1342 shadow->attach(context); | 1347 shadow->attach(context); |
1343 | 1348 |
1344 ContainerNode::attach(context); | 1349 ContainerNode::attach(context); |
1345 | 1350 |
1346 createPseudoElementIfNeeded(AFTER); | 1351 createPseudoElementIfNeeded(AFTER); |
1347 createPseudoElementIfNeeded(BACKDROP); | 1352 createPseudoElementIfNeeded(BACKDROP); |
1348 | 1353 |
1354 // We create the first-letter element after the :before, :after and | |
1355 // children are attached because the first letter text could come | |
1356 // from any of them. | |
1357 createPseudoElementIfNeeded(FIRST_LETTER); | |
1358 | |
1349 if (hasRareData() && !renderer()) { | 1359 if (hasRareData() && !renderer()) { |
1350 if (ActiveAnimations* activeAnimations = elementRareData()->activeAnimat ions()) { | 1360 if (ActiveAnimations* activeAnimations = elementRareData()->activeAnimat ions()) { |
1351 activeAnimations->cssAnimations().cancel(); | 1361 activeAnimations->cssAnimations().cancel(); |
1352 activeAnimations->setAnimationStyleChange(false); | 1362 activeAnimations->setAnimationStyleChange(false); |
1353 } | 1363 } |
1354 } | 1364 } |
1355 } | 1365 } |
1356 | 1366 |
1357 void Element::detach(const AttachContext& context) | 1367 void Element::detach(const AttachContext& context) |
1358 { | 1368 { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1498 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->old erShadowRoot()) { | 1508 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->old erShadowRoot()) { |
1499 if (root->shouldCallRecalcStyle(change)) | 1509 if (root->shouldCallRecalcStyle(change)) |
1500 root->recalcStyle(change); | 1510 root->recalcStyle(change); |
1501 } | 1511 } |
1502 recalcChildStyle(change); | 1512 recalcChildStyle(change); |
1503 } | 1513 } |
1504 | 1514 |
1505 updatePseudoElement(AFTER, change); | 1515 updatePseudoElement(AFTER, change); |
1506 updatePseudoElement(BACKDROP, change); | 1516 updatePseudoElement(BACKDROP, change); |
1507 | 1517 |
1518 // If our children have changed then we need to force the first-letter | |
1519 // checks as we don't know if they effected the first letter or not. | |
1520 // This can be seen when a child transitions from floating to | |
1521 // non-floating we have to take it into account for the first letter. | |
1522 updatePseudoElement(FIRST_LETTER, childNeedsStyleRecalc() ? Force : chan ge); | |
1523 | |
1508 clearChildNeedsStyleRecalc(); | 1524 clearChildNeedsStyleRecalc(); |
1509 } | 1525 } |
1510 | 1526 |
1511 if (hasCustomStyleCallbacks()) | 1527 if (hasCustomStyleCallbacks()) |
1512 didRecalcStyle(change); | 1528 didRecalcStyle(change); |
1513 | 1529 |
1514 if (change == Reattach) | 1530 if (change == Reattach) |
1515 reattachWhitespaceSiblings(nextTextSibling); | 1531 reattachWhitespaceSiblings(nextTextSibling); |
1516 } | 1532 } |
1517 | 1533 |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1730 return; | 1746 return; |
1731 | 1747 |
1732 if (!style || (styleAffectedByEmpty() && (!style->emptyState() || hasChildre n()))) | 1748 if (!style || (styleAffectedByEmpty() && (!style->emptyState() || hasChildre n()))) |
1733 document().styleResolver()->ensureUpdatedRuleFeatureSet().scheduleStyleI nvalidationForPseudoChange(CSSSelector::PseudoEmpty, *this); | 1749 document().styleResolver()->ensureUpdatedRuleFeatureSet().scheduleStyleI nvalidationForPseudoChange(CSSSelector::PseudoEmpty, *this); |
1734 } | 1750 } |
1735 | 1751 |
1736 void Element::childrenChanged(const ChildrenChange& change) | 1752 void Element::childrenChanged(const ChildrenChange& change) |
1737 { | 1753 { |
1738 ContainerNode::childrenChanged(change); | 1754 ContainerNode::childrenChanged(change); |
1739 | 1755 |
1756 if (change.isChildRemoval() && pseudoElement(FIRST_LETTER)) | |
1757 clearFirstLetterPseudoElement(); | |
esprehn
2014/09/30 09:00:30
Destroying it on every child mutation doesn't seem
dsinclair
2014/09/30 21:46:33
Removed. Re-ran the layout tests with this removed
| |
1758 | |
1740 checkForEmptyStyleChange(); | 1759 checkForEmptyStyleChange(); |
1741 if (!change.byParser && change.isChildElementChange()) | 1760 if (!change.byParser && change.isChildElementChange()) |
1742 checkForSiblingStyleChanges(change.type == ElementRemoved ? SiblingEleme ntRemoved : SiblingElementInserted, change.siblingBeforeChange, change.siblingAf terChange); | 1761 checkForSiblingStyleChanges(change.type == ElementRemoved ? SiblingEleme ntRemoved : SiblingElementInserted, change.siblingBeforeChange, change.siblingAf terChange); |
1743 | 1762 |
1744 if (ElementShadow* shadow = this->shadow()) | 1763 if (ElementShadow* shadow = this->shadow()) |
1745 shadow->setNeedsDistributionRecalc(); | 1764 shadow->setNeedsDistributionRecalc(); |
1746 } | 1765 } |
1747 | 1766 |
1748 void Element::finishParsingChildren() | 1767 void Element::finishParsingChildren() |
1749 { | 1768 { |
(...skipping 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2479 // attributes while we are iterating. | 2498 // attributes while we are iterating. |
2480 WillBeHeapVector<RefPtrWillBeMember<Attr> > attrNodesCopy(*attrNodes); | 2499 WillBeHeapVector<RefPtrWillBeMember<Attr> > attrNodesCopy(*attrNodes); |
2481 for (size_t i = 0; i < attrNodesCopy.size(); ++i) | 2500 for (size_t i = 0; i < attrNodesCopy.size(); ++i) |
2482 attrNodesCopy[i]->normalize(); | 2501 attrNodesCopy[i]->normalize(); |
2483 } | 2502 } |
2484 | 2503 |
2485 void Element::updatePseudoElement(PseudoId pseudoId, StyleRecalcChange change) | 2504 void Element::updatePseudoElement(PseudoId pseudoId, StyleRecalcChange change) |
2486 { | 2505 { |
2487 ASSERT(!needsStyleRecalc()); | 2506 ASSERT(!needsStyleRecalc()); |
2488 PseudoElement* element = pseudoElement(pseudoId); | 2507 PseudoElement* element = pseudoElement(pseudoId); |
2489 if (element && (change == UpdatePseudoElements || element->shouldCallRecalcS tyle(change))) { | 2508 |
2509 // We have a first-letter pseudoElement, but we no longer should have one. | |
2510 // This can happen if we change to a float, for example. We need to cleanup the | |
2511 // first-letter pseudoElement and then fix the text the original remaining | |
2512 // text renderer. | |
2513 if (pseudoId == FIRST_LETTER && element && !element->firstLetterTextRenderer ()) { | |
esprehn
2014/09/30 09:00:30
Why can't we handle this in the code below?
dsinclair
2014/09/30 21:46:33
Done.
Moved it into the if (change >= UpdatePseud
| |
2514 elementRareData()->setPseudoElement(pseudoId, nullptr); | |
2515 | |
2516 // For first-letter we need to force the style recalc here. The first letter | |
2517 // node's renderer needs to be forced to get a new style. This can be seen | |
2518 // in fast/css/first-letter-nested.html when we change the font size of | |
2519 // test_span_2. | |
esprehn
2014/09/30 09:00:30
Why? This comment explains what you're doing but n
dsinclair
2014/09/30 21:46:33
The caller is now doing a Force if the children ha
| |
2520 } else if (element && (change == UpdatePseudoElements || element->shouldCall RecalcStyle(change) | |
2521 || element->isFirstLetterPseudoElement())) { | |
2522 | |
2523 // If we're updating first letter, and the current first letter renderer | |
2524 // is not the same as the one we're currently using we need to re-create | |
2525 // the first letter renderer. | |
2526 if (pseudoId == FIRST_LETTER && element->firstLetterTextRenderer() != el ement->remainingTextRenderer()) { | |
esprehn
2014/09/30 09:00:30
firstLetterTextRenderer() doesn't seem like someth
dsinclair
2014/09/30 21:46:33
Done.
| |
2527 elementRareData()->setPseudoElement(pseudoId, nullptr); | |
2528 createPseudoElementIfNeeded(pseudoId); | |
2529 return; | |
2530 } | |
2490 | 2531 |
2491 // Need to clear the cached style if the PseudoElement wants a recalc so it | 2532 // Need to clear the cached style if the PseudoElement wants a recalc so it |
2492 // computes a new style. | 2533 // computes a new style. |
2493 if (element->needsStyleRecalc()) | 2534 if (element->needsStyleRecalc()) |
2494 renderer()->style()->removeCachedPseudoStyle(pseudoId); | 2535 renderer()->style()->removeCachedPseudoStyle(pseudoId); |
2495 | 2536 |
2496 // PseudoElement styles hang off their parent element's style so if we n eeded | 2537 // PseudoElement styles hang off their parent element's style so if we n eeded |
2497 // a style recalc we should Force one on the pseudo. | 2538 // a style recalc we should Force one on the pseudo. |
2498 // FIXME: We should figure out the right text sibling to pass. | 2539 // FIXME: We should figure out the right text sibling to pass. |
2499 element->recalcStyle(change == UpdatePseudoElements ? Force : change); | 2540 element->recalcStyle(change == UpdatePseudoElements ? Force : change); |
2500 | 2541 |
2501 // Wait until our parent is not displayed or pseudoElementRendererIsNeed ed | 2542 // Wait until our parent is not displayed or pseudoElementRendererIsNeed ed |
2502 // is false, otherwise we could continously create and destroy PseudoEle ments | 2543 // is false, otherwise we could continuously create and destroy PseudoEl ements |
2503 // when RenderObject::isChildAllowed on our parent returns false for the | 2544 // when RenderObject::isChildAllowed on our parent returns false for the |
2504 // PseudoElement's renderer for each style recalc. | 2545 // PseudoElement's renderer for each style recalc. |
2505 if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedP seudoStyle(pseudoId))) | 2546 if (!renderer() || !pseudoElementRendererIsNeeded(renderer()->getCachedP seudoStyle(pseudoId))) |
2506 elementRareData()->setPseudoElement(pseudoId, nullptr); | 2547 elementRareData()->setPseudoElement(pseudoId, nullptr); |
2507 } else if (change >= UpdatePseudoElements) { | 2548 } else if (change >= UpdatePseudoElements) { |
2508 createPseudoElementIfNeeded(pseudoId); | 2549 createPseudoElementIfNeeded(pseudoId); |
2509 } | 2550 } |
2510 } | 2551 } |
2511 | 2552 |
2512 void Element::createPseudoElementIfNeeded(PseudoId pseudoId) | 2553 void Element::createPseudoElementIfNeeded(PseudoId pseudoId) |
(...skipping 22 matching lines...) Expand all Loading... | |
2535 return hasRareData() ? elementRareData()->pseudoElement(pseudoId) : 0; | 2576 return hasRareData() ? elementRareData()->pseudoElement(pseudoId) : 0; |
2536 } | 2577 } |
2537 | 2578 |
2538 RenderObject* Element::pseudoElementRenderer(PseudoId pseudoId) const | 2579 RenderObject* Element::pseudoElementRenderer(PseudoId pseudoId) const |
2539 { | 2580 { |
2540 if (PseudoElement* element = pseudoElement(pseudoId)) | 2581 if (PseudoElement* element = pseudoElement(pseudoId)) |
2541 return element->renderer(); | 2582 return element->renderer(); |
2542 return 0; | 2583 return 0; |
2543 } | 2584 } |
2544 | 2585 |
2586 void Element::clearFirstLetterPseudoElement() | |
2587 { | |
2588 elementRareData()->setPseudoElement(FIRST_LETTER, nullptr); | |
2589 setNeedsStyleRecalc(SubtreeStyleChange); | |
esprehn
2014/09/30 09:00:30
Woah, this is crazy, why does removing it cause a
dsinclair
2014/09/30 21:46:33
Done. This call has been removed.
| |
2590 } | |
2591 | |
2545 bool Element::matches(const String& selectors, ExceptionState& exceptionState) | 2592 bool Element::matches(const String& selectors, ExceptionState& exceptionState) |
2546 { | 2593 { |
2547 SelectorQuery* selectorQuery = document().selectorQueryCache().add(AtomicStr ing(selectors), document(), exceptionState); | 2594 SelectorQuery* selectorQuery = document().selectorQueryCache().add(AtomicStr ing(selectors), document(), exceptionState); |
2548 if (!selectorQuery) | 2595 if (!selectorQuery) |
2549 return false; | 2596 return false; |
2550 return selectorQuery->matches(*this); | 2597 return selectorQuery->matches(*this); |
2551 } | 2598 } |
2552 | 2599 |
2553 DOMTokenList& Element::classList() | 2600 DOMTokenList& Element::classList() |
2554 { | 2601 { |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3260 const WrapperTypeInfo* wrapperType = wrapperTypeInfo(); | 3307 const WrapperTypeInfo* wrapperType = wrapperTypeInfo(); |
3261 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext , wrapperType, toScriptWrappableBase(), isolate); | 3308 v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext , wrapperType, toScriptWrappableBase(), isolate); |
3262 if (wrapper.IsEmpty()) | 3309 if (wrapper.IsEmpty()) |
3263 return v8::Handle<v8::Object>(); | 3310 return v8::Handle<v8::Object>(); |
3264 | 3311 |
3265 wrapper->SetPrototype(binding->prototype()); | 3312 wrapper->SetPrototype(binding->prototype()); |
3266 | 3313 |
3267 return V8DOMWrapper::associateObjectWithWrapperNonTemplate(this, wrapperType , wrapper, isolate); | 3314 return V8DOMWrapper::associateObjectWithWrapperNonTemplate(this, wrapperType , wrapper, isolate); |
3268 } | 3315 } |
3269 | 3316 |
3317 | |
3318 // CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter | |
3319 // "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps) , "close" (Pe), | |
3320 // "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that prec edes or follows the first letter should be included" | |
3321 static inline bool isPunctuationForFirstLetter(UChar c) | |
esprehn
2014/09/30 09:00:30
Lets put all this code in it's own class.
dsinclair
2014/09/30 21:46:33
Done.
| |
3322 { | |
3323 CharCategory charCategory = category(c); | |
3324 return charCategory == Punctuation_Open | |
3325 || charCategory == Punctuation_Close | |
3326 || charCategory == Punctuation_InitialQuote | |
3327 || charCategory == Punctuation_FinalQuote | |
3328 || charCategory == Punctuation_Other; | |
3329 } | |
3330 | |
3331 static inline bool isSpaceOrNewline(UChar c) | |
3332 { | |
3333 // Use isASCIISpace() for basic Latin-1. | |
3334 // This will include newlines, which aren't included in Unicode DirWS. | |
3335 return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF: :Unicode::WhiteSpaceNeutral; | |
3336 } | |
3337 | |
3338 static inline bool isSpaceForFirstLetter(UChar c) | |
3339 { | |
3340 return isSpaceOrNewline(c) || c == noBreakSpace; | |
3341 } | |
3342 | |
3343 unsigned Element::firstLetterLength(const String& text) const | |
esprehn
2014/09/30 09:00:30
ditto. Own class, own files.
dsinclair
2014/09/30 21:46:33
Done.
| |
3344 { | |
3345 unsigned length = 0; | |
3346 unsigned textLength = text.length(); | |
3347 | |
3348 // Account for leading spaces first. | |
3349 while (length < textLength && isSpaceForFirstLetter(text[length])) | |
3350 length++; | |
3351 | |
3352 // Now account for leading punctuation. | |
3353 while (length < textLength && isPunctuationForFirstLetter(text[length])) | |
3354 length++; | |
3355 | |
3356 // Bail if we didn't find a letter before the end of the text or before a sp ace. | |
3357 if (isSpaceForFirstLetter(text[length]) || (textLength && length == textLeng th)) | |
3358 return 0; | |
3359 | |
3360 // Account the next character for first letter. | |
3361 length++; | |
3362 | |
3363 // Keep looking allowed punctuation for the :first-letter. | |
3364 for (unsigned scanLength = length; scanLength < textLength; ++scanLength) { | |
3365 UChar c = text[scanLength]; | |
3366 | |
3367 if (!isPunctuationForFirstLetter(c)) | |
3368 break; | |
3369 | |
3370 length = scanLength + 1; | |
3371 } | |
3372 | |
3373 // FIXME: If textLength is 0, length may still be 1! | |
3374 return length; | |
3375 } | |
3376 | |
3377 RenderObject* Element::firstLetterTextRenderer() const | |
esprehn
2014/09/30 09:00:30
ditto
dsinclair
2014/09/30 21:46:33
Done.
| |
3378 { | |
3379 RenderObject* parentRenderer = renderer(); | |
3380 if (!parentRenderer | |
3381 || !parentRenderer->style()->hasPseudoStyle(FIRST_LETTER) | |
3382 || !parentRenderer->canHaveGeneratedChildren() | |
3383 || !(parentRenderer->isRenderBlockFlow() || parentRenderer->isRenderButt on())) | |
3384 return nullptr; | |
3385 | |
3386 // Drill down into our children and look for our first text child. | |
3387 RenderObject* firstLetterTextRenderer = parentRenderer->slowFirstChild(); | |
3388 while (firstLetterTextRenderer) { | |
3389 | |
3390 // This can be called when the first letter renderer is already in the t ree. We do not | |
3391 // want to consider that renderer for our text renderer so we go the sib ling. | |
3392 if (firstLetterTextRenderer->style() && firstLetterTextRenderer->style() ->styleType() == FIRST_LETTER) { | |
3393 firstLetterTextRenderer = firstLetterTextRenderer->nextSibling(); | |
3394 | |
3395 } else if (firstLetterTextRenderer->isText()) { | |
3396 // FIXME: If there is leading punctuation in a different RenderText than | |
3397 // the first letter, we'll not apply the correct style to it. | |
3398 if (firstLetterLength(toRenderText(firstLetterTextRenderer)->origina lText())) | |
3399 break; | |
3400 firstLetterTextRenderer = firstLetterTextRenderer->nextSibling(); | |
3401 | |
3402 } else if (firstLetterTextRenderer->isListMarker()) { | |
3403 firstLetterTextRenderer = firstLetterTextRenderer->nextSibling(); | |
3404 | |
3405 } else if (firstLetterTextRenderer->isFloatingOrOutOfFlowPositioned()) { | |
3406 if (firstLetterTextRenderer->style()->styleType() == FIRST_LETTER) { | |
3407 firstLetterTextRenderer = firstLetterTextRenderer->slowFirstChil d(); | |
3408 break; | |
3409 } | |
3410 firstLetterTextRenderer = firstLetterTextRenderer->nextSibling(); | |
3411 | |
3412 } else if (firstLetterTextRenderer->isReplaced() || firstLetterTextRende rer->isRenderButton() | |
3413 || firstLetterTextRenderer->isMenuList()) { | |
3414 return nullptr; | |
3415 | |
3416 } else if (firstLetterTextRenderer->style()->hasPseudoStyle(FIRST_LETTER ) | |
3417 && firstLetterTextRenderer->canHaveGeneratedChildren()) { | |
3418 // Let the child handle it when it's attached. | |
3419 return nullptr; | |
3420 | |
3421 } else { | |
3422 firstLetterTextRenderer = firstLetterTextRenderer->slowFirstChild(); | |
3423 } | |
3424 } | |
3425 | |
3426 // No first letter text to display, we're done. | |
3427 // FIXME: This black-list of disallowed RenderText subclasses is fragile. | |
3428 // Should counter be on this list? What about RenderTextFragment? | |
3429 if (!firstLetterTextRenderer || !firstLetterTextRenderer->isText() | |
3430 || firstLetterTextRenderer->isBR() || toRenderText(firstLetterTextRender er)->isWordBreak()) | |
3431 return nullptr; | |
3432 | |
3433 return firstLetterTextRenderer; | |
3434 } | |
3435 | |
3270 } // namespace blink | 3436 } // namespace blink |
OLD | NEW |