2367
2368Element::DirAttributeState Element::dir() const
2369{
2370 static NeverDestroyed<AtomicString> ltrValue("ltr", AtomicString::ConstructFromLiteral);
2371 static NeverDestroyed<AtomicString> rtlValue("rtl", AtomicString::ConstructFromLiteral);
2372 static NeverDestroyed<AtomicString> autoValue("auto", AtomicString::ConstructFromLiteral);
2373 const AtomicString& value = fastGetAttribute(dirAttr);
2374
2375 if (equalIgnoringCase(value, ltrValue))
2376 return DirLTR;
2377 if (equalIgnoringCase(value, rtlValue))
2378 return DirRTL;
2379 if (equalIgnoringCase(value, autoValue))
2380 return DirAuto;
2381 return DirUnknown;
2382}
2383
2384TextDirection Element::computeInheritedDirection() const
2385{
2386 DirAttributeState d = dir();
2387 TextDirection td;
2388
2389 if (d == DirLTR)
2390 return LTR;
2391
2392 if (d == DirRTL)
2393 return RTL;
2394
2395 if (is<HTMLInputElement>(*this)) {
2396 HTMLInputElement& input = downcast<HTMLInputElement>(const_cast<Element&>(*this));
2397 if (d == DirUnknown && input.isTelephoneField())
2398 return LTR;
2399 if (d == DirAuto && (input.isTextField() ||
2400 input.isSearchField() ||
2401 input.isTelephoneField() ||
2402 input.isURLField() ||
2403 input.isEmailField())) {
2404 if (evalContentDirectionality(td))
2405 return td;
2406
2407 }
2408
2409 } else if (is<HTMLTextAreaElement>(*this)) {
2410 if (d == DirAuto && evalContentDirectionality(td))
2411 return td;
2412 } else if (d == DirAuto || (d == DirUnknown && equalIgnoringCase(nodeName(), "bdi"))) {
2413 if (evalContentDirectionality(td)) {
2414 return td;
2415 }
2416
2417 } else if (d == DirUnknown) {
2418 if (isDocumentNode())
2419 return LTR;
2420 if (parentElement())
2421 return parentElement()->computeInheritedDirection();
2422 }
2423
2424 return LTR; // Must ASSERT we don't get here
2425}
2426
2427bool Element::evalContentDirectionality(TextDirection& direction) const {
2428 bool foundDirection = false;
2429 UCharDirection charDirection;
2430
2431 if (is<HTMLTextFormControlElement>(*this)) {
2432 HTMLTextFormControlElement& textElement = downcast<HTMLTextFormControlElement>(const_cast<Element&>(*this));
2433 bool hasStrongDirectionality;
2434 charDirection = textElement.value().defaultWritingDirection(&hasStrongDirectionality);
2435 foundDirection = true;
2436 } else {
2437 Node* node = firstChild();
2438 while (node) {
2439 // Skip bdi, script, style and text form controls.
2440 if (equalIgnoringCase(node->nodeName(), "bdi") || node->hasTagName(scriptTag) || node->hasTagName(styleTag)
2441 || (is<Element>(*node) && downcast<Element>(*node).isTextFormControl())) {
2442 node = NodeTraversal::nextSkippingChildren(*node, this);
2443 continue;
2444 }
2445
2446 // Skip elements with valid dir attribute
2447 if (is<Element>(*node)) {
2448 Element& e = downcast<Element>(*node);
2449 if (e.dir() != DirUnknown) {
2450 node = NodeTraversal::nextSkippingChildren(*node, this);
2451 continue;
2452 }
2453 }
2454
2455 if (node->isTextNode()) {
2456 bool hasStrongDirectionality;
2457 charDirection = node->textContent(true).defaultWritingDirection(&hasStrongDirectionality);
2458 foundDirection = true;
2459 }
2460 node = NodeTraversal::next(*node, this);
2461 }
2462 }
2463
2464 if (foundDirection) {
2465 direction = (charDirection == U_LEFT_TO_RIGHT)? LTR : RTL;
2466 return true;
2467 }
2468
2469 return false;
2470}
2471