static Directionality GetDirectionFromText(const nsTextFragment* aFrag, uint32_t* aFirstStrong = nullptr) { if (aFrag->Is2b()) { return GetDirectionFromText(aFrag->Get2b(), aFrag->GetLength(), aFirstStrong); } return GetDirectionFromText(aFrag->Get1b(), aFrag->GetLength(), aFirstStrong); }
/** * Set the directionality of a node with dir=auto as defined in * http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality * * @param[in] aStartAfterNode as an optimization, a caller may pass in a node * from which to begin walking the descendants of aElement, if it is * known that all text nodes before this node do not contain any * strong directional characters * @return the text node containing the character that determined the direction */ static nsINode* WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true, nsINode* aStartAfterNode = nullptr) { MOZ_ASSERT(aElement, "aElement is null"); nsIContent* child; if (aStartAfterNode && nsContentUtils::ContentIsDescendantOf(aStartAfterNode, aElement)) { #ifdef DEBUG child = aElement->GetFirstChild(); while (child && child != aStartAfterNode) { if (child->NodeType() == nsIDOMNode::TEXT_NODE) { MOZ_ASSERT(GetDirectionFromText(child->GetText()) == eDir_NotSet, "Strong directional characters before aStartAfterNode"); } child = child->GetNextNode(aElement); } #endif child = aStartAfterNode->GetNextNode(aElement); } else { child = aElement->GetFirstChild(); } while (child) { if (child->IsElement() && (DoesNotParticipateInAutoDirection(child->AsElement()) || child->NodeInfo()->Equals(nsGkAtoms::bdi) || child->HasFixedDir())) { child = child->GetNextNonChildNode(aElement); continue; } if (child->NodeType() == nsIDOMNode::TEXT_NODE) { Directionality textNodeDir = GetDirectionFromText(child->GetText()); if (textNodeDir != eDir_NotSet) { // We found a descendant text node with strong directional characters. // Set the directionality of aElement to the corresponding value. aElement->SetDirectionality(textNodeDir, aNotify); return child; } } child = child->GetNextNode(aElement); } // We walked all the descendants without finding a text node with strong // directional characters. Set the directionality to LTR aElement->SetDirectionality(eDir_LTR, aNotify); return nullptr; }
/** * Set the directionality of a node with dir=auto as defined in * http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-directionality * * @return the text node containing the character that determined the direction */ static nsINode* WalkDescendantsSetDirectionFromText(Element* aElement, bool aNotify = true) { MOZ_ASSERT(aElement, "aElement is null"); if (DoesNotParticipateInAutoDirection(aElement)) { return nullptr; } nsIContent* child = aElement->GetFirstChild(); while (child) { if (child->IsElement() && DoesNotAffectDirectionOfAncestors(child->AsElement())) { child = child->GetNextNonChildNode(aElement); continue; } if (child->NodeType() == nsIDOMNode::TEXT_NODE) { Directionality textNodeDir = GetDirectionFromText(child->GetText()); if (textNodeDir != eDir_NotSet) { // We found a descendant text node with strong directional characters. // Set the directionality of aElement to the corresponding value. aElement->SetDirectionality(textNodeDir, aNotify); return child; } } child = child->GetNextNode(aElement); } // We walked all the descendants without finding a text node with strong // directional characters. Set the directionality to LTR aElement->SetDirectionality(eDir_LTR, aNotify); return nullptr; }
void SetDirectionalityFromValue(Element* aElement, const nsAString& value, bool aNotify) { Directionality dir = GetDirectionFromText(PromiseFlatString(value).get(), value.Length()); if (dir == eDir_NotSet) { dir = eDir_LTR; } aElement->SetDirectionality(dir, aNotify); }
void ResetDirectionSetByTextNode(nsTextNode* aTextNode) { if (!NodeAffectsDirAutoAncestor(aTextNode)) { return; } Directionality dir = GetDirectionFromText(aTextNode->GetText()); if (dir != eDir_NotSet && aTextNode->HasTextNodeDirectionalityMap()) { nsTextNodeDirectionalityMap::ResetTextNodeDirection(aTextNode); } }
void SetDirectionFromNewTextNode(nsTextNode* aTextNode) { if (!NodeAffectsDirAutoAncestor(aTextNode)) { return; } Directionality dir = GetDirectionFromText(aTextNode->GetText()); if (dir != eDir_NotSet) { SetAncestorDirectionIfAuto(aTextNode, dir); } }
void SetDirectionFromChangedTextNode(nsIContent* aTextNode, uint32_t aOffset, const PRUnichar* aBuffer, uint32_t aLength, bool aNotify) { if (!NodeAffectsDirAutoAncestor(aTextNode)) { return; } uint32_t firstStrong; Directionality oldDir = GetDirectionFromText(aTextNode->GetText(), &firstStrong); if (aOffset > firstStrong) { return; } Directionality newDir = GetDirectionFromText(aBuffer, aLength); if (newDir == eDir_NotSet) { if (oldDir != eDir_NotSet && aTextNode->HasTextNodeDirectionalityMap()) { // This node used to have a strong directional character but no // longer does. ResetTextNodeDirection() will re-resolve the // directionality of any elements whose directionality was // determined by this node. nsTextNodeDirectionalityMap::ResetTextNodeDirection(aTextNode); } } else { // This node has a strong directional character. If it has a // TextNodeDirectionalityMap property, it already determines the // directionality of some element(s), so call UpdateTextNodeDirection to // reresolve their directionality. Otherwise call // SetAncestorDirectionIfAuto to find ancestor elements which should // have their directionality determined by this node. if (aTextNode->HasTextNodeDirectionalityMap()) { nsTextNodeDirectionalityMap::UpdateTextNodeDirection(aTextNode, newDir); } else { SetAncestorDirectionIfAuto(aTextNode, newDir, aNotify); } } }