Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(874)

Side by Side Diff: Source/core/dom/Element.cpp

Issue 571603003: Convert first letter into a pseudo element. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698