mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 20:30:41 +00:00
Bug 1852478 - Convert CSS white-space
into a shorthand that expands to white-space-collapse
and text-wrap-mode
longhands. r=firefox-style-system-reviewers,emilio
Note that although this builds, it would (by itself) result in some test breakage; this is resolved in the following patches that build on this. Differential Revision: https://phabricator.services.mozilla.com/D198790
This commit is contained in:
parent
9901e70871
commit
5f45c5f18d
@ -131,7 +131,7 @@ use.counter.error:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 2299 use counter metrics (excludes denominators).
|
||||
# Total of 2303 use counter metrics (excludes denominators).
|
||||
# Total of 356 'page' use counters.
|
||||
use.counter.page:
|
||||
svgsvgelement_getelementbyid:
|
||||
@ -15667,7 +15667,7 @@ use.counter.deprecated_ops.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 693 'CSS (page)' use counters.
|
||||
# Total of 695 'CSS (page)' use counters.
|
||||
use.counter.css.page:
|
||||
css_align_content:
|
||||
type: counter
|
||||
@ -17641,6 +17641,23 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_text_wrap_mode:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a page used the CSS property text-wrap-mode.
|
||||
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_touch_action:
|
||||
type: counter
|
||||
description: >
|
||||
@ -17794,10 +17811,10 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_white_space:
|
||||
css_white_space_collapse:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a page used the CSS property white-space.
|
||||
Whether a page used the CSS property white-space-collapse.
|
||||
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
@ -23183,6 +23200,23 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_white_space:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a page used the CSS property white-space.
|
||||
Compare against `use.counter.top_level_content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_webkit_text_stroke:
|
||||
type: counter
|
||||
description: >
|
||||
@ -27450,7 +27484,7 @@ use.counter.css.page:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
# Total of 693 'CSS (document)' use counters.
|
||||
# Total of 695 'CSS (document)' use counters.
|
||||
use.counter.css.doc:
|
||||
css_align_content:
|
||||
type: counter
|
||||
@ -29424,6 +29458,23 @@ use.counter.css.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_text_wrap_mode:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a document used the CSS property text-wrap-mode.
|
||||
Compare against `use.counter.content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_touch_action:
|
||||
type: counter
|
||||
description: >
|
||||
@ -29577,10 +29628,10 @@ use.counter.css.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_white_space:
|
||||
css_white_space_collapse:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a document used the CSS property white-space.
|
||||
Whether a document used the CSS property white-space-collapse.
|
||||
Compare against `use.counter.content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
@ -34966,6 +35017,23 @@ use.counter.css.doc:
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_white_space:
|
||||
type: counter
|
||||
description: >
|
||||
Whether a document used the CSS property white-space.
|
||||
Compare against `use.counter.content_documents_destroyed`
|
||||
to calculate the rate.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1852098
|
||||
notification_emails:
|
||||
- dom-core@mozilla.com
|
||||
- emilio@mozilla.com
|
||||
expires: never
|
||||
send_in_pings:
|
||||
- use-counters
|
||||
|
||||
css_webkit_text_stroke:
|
||||
type: counter
|
||||
description: >
|
||||
|
@ -38,8 +38,11 @@ void HTMLPreElement::MapAttributesIntoRule(
|
||||
MappedDeclarationsBuilder& aBuilder) {
|
||||
// wrap: empty
|
||||
if (aBuilder.GetAttr(nsGkAtoms::wrap)) {
|
||||
aBuilder.SetKeywordValue(eCSSProperty_white_space,
|
||||
StyleWhiteSpace::PreWrap);
|
||||
// Equivalent to expanding `white-space: pre-wrap`
|
||||
aBuilder.SetKeywordValue(eCSSProperty_white_space_collapse,
|
||||
StyleWhiteSpaceCollapse::Preserve);
|
||||
aBuilder.SetKeywordValue(eCSSProperty_text_wrap_mode,
|
||||
StyleTextWrapMode::Wrap);
|
||||
}
|
||||
|
||||
nsGenericHTMLElement::MapCommonAttributesInto(aBuilder);
|
||||
|
@ -163,7 +163,7 @@ void HTMLTableCellElement::MapAttributesIntoRule(
|
||||
MappedDeclarationsBuilder& aBuilder) {
|
||||
MapImageSizeAttributesInto(aBuilder);
|
||||
|
||||
if (!aBuilder.PropertyIsSet(eCSSProperty_white_space)) {
|
||||
if (!aBuilder.PropertyIsSet(eCSSProperty_text_wrap_mode)) {
|
||||
// nowrap: enum
|
||||
if (aBuilder.GetAttr(nsGkAtoms::nowrap)) {
|
||||
// See if our width is not a nonzero integer width.
|
||||
@ -171,8 +171,8 @@ void HTMLTableCellElement::MapAttributesIntoRule(
|
||||
nsCompatibility mode = aBuilder.Document().GetCompatibilityMode();
|
||||
if (!value || value->Type() != nsAttrValue::eInteger ||
|
||||
value->GetIntegerValue() == 0 || eCompatibility_NavQuirks != mode) {
|
||||
aBuilder.SetKeywordValue(eCSSProperty_white_space,
|
||||
StyleWhiteSpace::Nowrap);
|
||||
aBuilder.SetKeywordValue(eCSSProperty_text_wrap_mode,
|
||||
StyleTextWrapMode::Nowrap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -365,12 +365,14 @@ bool HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
|
||||
void HTMLTextAreaElement::MapAttributesIntoRule(
|
||||
MappedDeclarationsBuilder& aBuilder) {
|
||||
// wrap=off
|
||||
if (!aBuilder.PropertyIsSet(eCSSProperty_white_space)) {
|
||||
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::wrap);
|
||||
if (value && value->Type() == nsAttrValue::eString &&
|
||||
value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
|
||||
aBuilder.SetKeywordValue(eCSSProperty_white_space, StyleWhiteSpace::Pre);
|
||||
}
|
||||
const nsAttrValue* value = aBuilder.GetAttr(nsGkAtoms::wrap);
|
||||
if (value && value->Type() == nsAttrValue::eString &&
|
||||
value->Equals(nsGkAtoms::OFF, eIgnoreCase)) {
|
||||
// Equivalent to expanding `white-space; pre`
|
||||
aBuilder.SetKeywordValue(eCSSProperty_white_space_collapse,
|
||||
StyleWhiteSpaceCollapse::Preserve);
|
||||
aBuilder.SetKeywordValue(eCSSProperty_text_wrap_mode,
|
||||
StyleTextWrapMode::Nowrap);
|
||||
}
|
||||
|
||||
nsGenericHTMLFormControlElementWithState::MapDivAlignAttributeInto(aBuilder);
|
||||
|
@ -89,8 +89,8 @@ bool EditorUtils::IsDescendantOf(const nsINode& aNode, const nsINode& aParent,
|
||||
}
|
||||
|
||||
// static
|
||||
Maybe<StyleWhiteSpace> EditorUtils::GetComputedWhiteSpaceStyle(
|
||||
const nsIContent& aContent) {
|
||||
Maybe<std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode>>
|
||||
EditorUtils::GetComputedWhiteSpaceStyles(const nsIContent& aContent) {
|
||||
if (MOZ_UNLIKELY(!aContent.IsElement() && !aContent.GetParentElement())) {
|
||||
return Nothing();
|
||||
}
|
||||
@ -101,7 +101,9 @@ Maybe<StyleWhiteSpace> EditorUtils::GetComputedWhiteSpaceStyle(
|
||||
if (NS_WARN_IF(!elementStyle)) {
|
||||
return Nothing();
|
||||
}
|
||||
return Some(elementStyle->StyleText()->mWhiteSpace);
|
||||
const auto* styleText = elementStyle->StyleText();
|
||||
return Some(
|
||||
std::pair(styleText->mWhiteSpaceCollapse, styleText->mTextWrapMode));
|
||||
}
|
||||
|
||||
// static
|
||||
@ -164,7 +166,8 @@ bool EditorUtils::IsOnlyNewLinePreformatted(const nsIContent& aContent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return elementStyle->StyleText()->mWhiteSpace == StyleWhiteSpace::PreLine;
|
||||
return elementStyle->StyleText()->mWhiteSpaceCollapse ==
|
||||
StyleWhiteSpaceCollapse::PreserveBreaks;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -401,10 +401,10 @@ class EditorUtils final {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get computed white-space style of aContent.
|
||||
* Get the two longhands that make up computed white-space style of aContent.
|
||||
*/
|
||||
static Maybe<StyleWhiteSpace> GetComputedWhiteSpaceStyle(
|
||||
const nsIContent& aContent);
|
||||
static Maybe<std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode>>
|
||||
GetComputedWhiteSpaceStyles(const nsIContent& aContent);
|
||||
|
||||
/**
|
||||
* IsWhiteSpacePreformatted() checks the style info for the node for the
|
||||
@ -421,7 +421,7 @@ class EditorUtils final {
|
||||
/**
|
||||
* IsOnlyNewLinePreformatted() checks whether the linefeed characters are
|
||||
* preformated but white-spaces are collapsed, or otherwise. I.e., this
|
||||
* returns true only when `white-space:pre-line`.
|
||||
* returns true only when `white-space-collapse:pre-line`.
|
||||
*/
|
||||
static bool IsOnlyNewLinePreformatted(const nsIContent& aContent);
|
||||
|
||||
|
@ -5353,8 +5353,10 @@ HTMLEditor::AutoMoveOneLineHandler::ConsiderWhetherPreserveWhiteSpaceStyle(
|
||||
// If the content has different `white-space` style from <pre>, we
|
||||
// shouldn't treat it as a descendant of <pre> because web apps or
|
||||
// the user intent to treat the white-spaces in aContent not as `pre`.
|
||||
if (EditorUtils::GetComputedWhiteSpaceStyle(aContent).valueOr(
|
||||
StyleWhiteSpace::Normal) != StyleWhiteSpace::Pre) {
|
||||
if (EditorUtils::GetComputedWhiteSpaceStyles(aContent).valueOr(std::pair(
|
||||
StyleWhiteSpaceCollapse::Collapse, StyleTextWrapMode::Wrap)) !=
|
||||
std::pair(StyleWhiteSpaceCollapse::Preserve,
|
||||
StyleTextWrapMode::Nowrap)) {
|
||||
return false;
|
||||
}
|
||||
for (const Element* element :
|
||||
@ -5801,52 +5803,65 @@ Result<MoveNodeResult, nsresult> HTMLEditor::MoveNodeOrChildrenWithTransaction(
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(aPointToInsert.IsInContentNode());
|
||||
|
||||
const auto destWhiteSpaceStyle = [&]() -> Maybe<StyleWhiteSpace> {
|
||||
const auto destWhiteSpaceStyles =
|
||||
[&]() -> Maybe<std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode>> {
|
||||
if (aPreserveWhiteSpaceStyle == PreserveWhiteSpaceStyle::No ||
|
||||
!aPointToInsert.IsInContentNode()) {
|
||||
return Nothing();
|
||||
}
|
||||
auto style = EditorUtils::GetComputedWhiteSpaceStyle(
|
||||
auto styles = EditorUtils::GetComputedWhiteSpaceStyles(
|
||||
*aPointToInsert.ContainerAs<nsIContent>());
|
||||
if (NS_WARN_IF(style.isSome() &&
|
||||
style.value() == StyleWhiteSpace::PreSpace)) {
|
||||
if (NS_WARN_IF(styles.isSome() &&
|
||||
styles.value().first ==
|
||||
StyleWhiteSpaceCollapse::PreserveSpaces)) {
|
||||
return Nothing();
|
||||
}
|
||||
return style;
|
||||
return styles;
|
||||
}();
|
||||
const auto srcWhiteSpaceStyle = [&]() -> Maybe<StyleWhiteSpace> {
|
||||
const auto srcWhiteSpaceStyles =
|
||||
[&]() -> Maybe<std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode>> {
|
||||
if (aPreserveWhiteSpaceStyle == PreserveWhiteSpaceStyle::No) {
|
||||
return Nothing();
|
||||
}
|
||||
auto style = EditorUtils::GetComputedWhiteSpaceStyle(aContentToMove);
|
||||
if (NS_WARN_IF(style.isSome() &&
|
||||
style.value() == StyleWhiteSpace::PreSpace)) {
|
||||
auto styles = EditorUtils::GetComputedWhiteSpaceStyles(aContentToMove);
|
||||
if (NS_WARN_IF(styles.isSome() &&
|
||||
styles.value().first ==
|
||||
StyleWhiteSpaceCollapse::PreserveSpaces)) {
|
||||
return Nothing();
|
||||
}
|
||||
return style;
|
||||
return styles;
|
||||
}();
|
||||
const auto GetWhiteSpaceStyleValue = [](StyleWhiteSpace aStyleWhiteSpace) {
|
||||
switch (aStyleWhiteSpace) {
|
||||
case StyleWhiteSpace::Normal:
|
||||
return u"normal"_ns;
|
||||
case StyleWhiteSpace::Pre:
|
||||
return u"pre"_ns;
|
||||
case StyleWhiteSpace::Nowrap:
|
||||
return u"nowrap"_ns;
|
||||
case StyleWhiteSpace::PreWrap:
|
||||
return u"pre-wrap"_ns;
|
||||
case StyleWhiteSpace::PreLine:
|
||||
return u"pre-line"_ns;
|
||||
case StyleWhiteSpace::BreakSpaces:
|
||||
return u"break-spaces"_ns;
|
||||
case StyleWhiteSpace::PreSpace:
|
||||
MOZ_ASSERT_UNREACHABLE("Don't handle -moz-pre-space");
|
||||
return u""_ns;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Handle the new white-space value");
|
||||
return u""_ns;
|
||||
}
|
||||
};
|
||||
// Get the `white-space` shorthand form for the given collapse + mode pair.
|
||||
const auto GetWhiteSpaceStyleValue =
|
||||
[](std::pair<StyleWhiteSpaceCollapse, StyleTextWrapMode> aStyles) {
|
||||
if (aStyles.second == StyleTextWrapMode::Wrap) {
|
||||
switch (aStyles.first) {
|
||||
case StyleWhiteSpaceCollapse::Collapse:
|
||||
return u"normal"_ns;
|
||||
case StyleWhiteSpaceCollapse::Preserve:
|
||||
return u"pre-wrap"_ns;
|
||||
case StyleWhiteSpaceCollapse::PreserveBreaks:
|
||||
return u"pre-line"_ns;
|
||||
case StyleWhiteSpaceCollapse::PreserveSpaces:
|
||||
return u"preserve-spaces"_ns;
|
||||
case StyleWhiteSpaceCollapse::BreakSpaces:
|
||||
return u"break-spaces"_ns;
|
||||
}
|
||||
} else {
|
||||
switch (aStyles.first) {
|
||||
case StyleWhiteSpaceCollapse::Collapse:
|
||||
return u"nowrap"_ns;
|
||||
case StyleWhiteSpaceCollapse::Preserve:
|
||||
return u"pre"_ns;
|
||||
case StyleWhiteSpaceCollapse::PreserveBreaks:
|
||||
return u"nowrap preserve-breaks"_ns;
|
||||
case StyleWhiteSpaceCollapse::PreserveSpaces:
|
||||
return u"nowrap preserve-spaces"_ns;
|
||||
case StyleWhiteSpaceCollapse::BreakSpaces:
|
||||
return u"nowrap break-spaces"_ns;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (aRemoveIfCommentNode == RemoveIfCommentNode::Yes &&
|
||||
aContentToMove.IsComment()) {
|
||||
@ -5872,15 +5887,15 @@ Result<MoveNodeResult, nsresult> HTMLEditor::MoveNodeOrChildrenWithTransaction(
|
||||
// Preserve white-space in the new position with using `style` attribute.
|
||||
// This is additional path from point of view of our traditional behavior.
|
||||
// Therefore, ignore errors especially if we got unexpected DOM tree.
|
||||
if (destWhiteSpaceStyle.isSome() && srcWhiteSpaceStyle.isSome() &&
|
||||
destWhiteSpaceStyle.value() != srcWhiteSpaceStyle.value()) {
|
||||
if (destWhiteSpaceStyles.isSome() && srcWhiteSpaceStyles.isSome() &&
|
||||
destWhiteSpaceStyles.value() != srcWhiteSpaceStyles.value()) {
|
||||
// Set `white-space` with `style` attribute if it's nsStyledElement.
|
||||
if (nsStyledElement* styledElement =
|
||||
nsStyledElement::FromNode(&aContentToMove)) {
|
||||
DebugOnly<nsresult> rvIgnored =
|
||||
CSSEditUtils::SetCSSPropertyWithTransaction(
|
||||
*this, MOZ_KnownLive(*styledElement), *nsGkAtoms::white_space,
|
||||
GetWhiteSpaceStyleValue(srcWhiteSpaceStyle.value()));
|
||||
GetWhiteSpaceStyleValue(srcWhiteSpaceStyles.value()));
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return Err(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
@ -5900,7 +5915,7 @@ Result<MoveNodeResult, nsresult> HTMLEditor::MoveNodeOrChildrenWithTransaction(
|
||||
}
|
||||
nsAutoString styleAttrValue(u"white-space: "_ns);
|
||||
styleAttrValue.Append(
|
||||
GetWhiteSpaceStyleValue(srcWhiteSpaceStyle.value()));
|
||||
GetWhiteSpaceStyleValue(srcWhiteSpaceStyles.value()));
|
||||
IgnoredErrorResult error;
|
||||
newSpanElement->SetAttr(nsGkAtoms::style, styleAttrValue, error);
|
||||
NS_WARNING_ASSERTION(!error.Failed(),
|
||||
|
@ -724,8 +724,8 @@ Result<EditActionResult, nsresult> WhiteSpaceVisibilityKeeper::
|
||||
// a bug to manage only the change.
|
||||
(aLeftBlockElement.NodeInfo()->NameAtom() ==
|
||||
aRightBlockElement.NodeInfo()->NameAtom() &&
|
||||
EditorUtils::GetComputedWhiteSpaceStyle(aLeftBlockElement) ==
|
||||
EditorUtils::GetComputedWhiteSpaceStyle(aRightBlockElement))) {
|
||||
EditorUtils::GetComputedWhiteSpaceStyles(aLeftBlockElement) ==
|
||||
EditorUtils::GetComputedWhiteSpaceStyles(aRightBlockElement))) {
|
||||
// Nodes are same type. merge them.
|
||||
EditorDOMPoint atFirstChildOfRightNode;
|
||||
nsresult rv = aHTMLEditor.JoinNearestEditableNodesWithTransaction(
|
||||
|
@ -9109,8 +9109,8 @@ nsresult nsIFrame::PeekOffsetForWord(PeekOffsetStruct* aPos, int32_t aOffset) {
|
||||
// significant.
|
||||
if (next.mJumpedLine && wordSelectEatSpace &&
|
||||
current.mFrame->HasSignificantTerminalNewline() &&
|
||||
current.mFrame->StyleText()->mWhiteSpace !=
|
||||
StyleWhiteSpace::PreLine) {
|
||||
current.mFrame->StyleText()->mWhiteSpaceCollapse !=
|
||||
StyleWhiteSpaceCollapse::PreserveBreaks) {
|
||||
current.mOffset -= 1;
|
||||
}
|
||||
break;
|
||||
|
@ -781,7 +781,8 @@ static bool IsTrimmableSpace(const nsTextFragment* aFrag, uint32_t aPos,
|
||||
!IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
|
||||
case '\n':
|
||||
return !aStyleText->NewlineIsSignificantStyle() &&
|
||||
aStyleText->mWhiteSpace != mozilla::StyleWhiteSpace::PreSpace;
|
||||
aStyleText->mWhiteSpaceCollapse !=
|
||||
StyleWhiteSpaceCollapse::PreserveSpaces;
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\f':
|
||||
@ -1171,27 +1172,23 @@ static bool TextContainsLineBreakerWhiteSpace(const void* aText,
|
||||
|
||||
static nsTextFrameUtils::CompressionMode GetCSSWhitespaceToCompressionMode(
|
||||
nsTextFrame* aFrame, const nsStyleText* aStyleText) {
|
||||
switch (aStyleText->mWhiteSpace) {
|
||||
case StyleWhiteSpace::Normal:
|
||||
case StyleWhiteSpace::Nowrap:
|
||||
switch (aStyleText->mWhiteSpaceCollapse) {
|
||||
case StyleWhiteSpaceCollapse::Collapse:
|
||||
return nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE;
|
||||
case StyleWhiteSpace::Pre:
|
||||
case StyleWhiteSpace::PreWrap:
|
||||
case StyleWhiteSpace::BreakSpaces:
|
||||
case StyleWhiteSpaceCollapse::PreserveBreaks:
|
||||
return nsTextFrameUtils::COMPRESS_WHITESPACE;
|
||||
case StyleWhiteSpaceCollapse::Preserve:
|
||||
case StyleWhiteSpaceCollapse::PreserveSpaces:
|
||||
case StyleWhiteSpaceCollapse::BreakSpaces:
|
||||
if (!aStyleText->NewlineIsSignificant(aFrame)) {
|
||||
// If newline is set to be preserved, but then suppressed,
|
||||
// transform newline to space.
|
||||
return nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE;
|
||||
}
|
||||
return nsTextFrameUtils::COMPRESS_NONE;
|
||||
case StyleWhiteSpace::PreSpace:
|
||||
return nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE;
|
||||
case StyleWhiteSpace::PreLine:
|
||||
return nsTextFrameUtils::COMPRESS_WHITESPACE;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown white-space value");
|
||||
return nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE;
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown white-space-collapse value");
|
||||
return nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE;
|
||||
}
|
||||
|
||||
struct FrameTextTraversal {
|
||||
@ -9539,7 +9536,8 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||
}
|
||||
bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() ||
|
||||
HasAnyStateBits(TEXT_IS_IN_TOKEN_MATHML);
|
||||
bool isBreakSpaces = textStyle->mWhiteSpace == StyleWhiteSpace::BreakSpaces;
|
||||
bool isBreakSpaces =
|
||||
textStyle->mWhiteSpaceCollapse == StyleWhiteSpaceCollapse::BreakSpaces;
|
||||
// allow whitespace to overflow the container
|
||||
bool whitespaceCanHang = textStyle->WhiteSpaceCanHangOrVisuallyCollapse();
|
||||
gfxBreakPriority breakPriority = aLineLayout.LastOptionalBreakPriority();
|
||||
@ -10307,9 +10305,9 @@ bool nsTextFrame::IsEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isEmpty =
|
||||
IsAllWhitespace(TextFragment(), textStyle->mWhiteSpace !=
|
||||
mozilla::StyleWhiteSpace::PreLine);
|
||||
bool isEmpty = IsAllWhitespace(TextFragment(),
|
||||
textStyle->mWhiteSpaceCollapse !=
|
||||
StyleWhiteSpaceCollapse::PreserveBreaks);
|
||||
AddStateBits(isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
|
||||
return isEmpty;
|
||||
}
|
||||
|
@ -137,7 +137,8 @@ rusty-enums = [
|
||||
"mozilla::StyleListStylePosition",
|
||||
"mozilla::StylePointerEvents",
|
||||
"mozilla::StyleScrollbarWidth",
|
||||
"mozilla::StyleWhiteSpace",
|
||||
"mozilla::StyleWhiteSpaceCollapse",
|
||||
"mozilla::StyleTextWrapMode",
|
||||
"mozilla::StyleTextRendering",
|
||||
"mozilla::StyleFlexDirection",
|
||||
"mozilla::StyleStrokeLinecap",
|
||||
|
@ -389,16 +389,21 @@ enum class StyleVisibility : uint8_t {
|
||||
};
|
||||
|
||||
// See nsStyleText
|
||||
enum class StyleWhiteSpace : uint8_t {
|
||||
Normal = 0,
|
||||
Pre,
|
||||
Nowrap,
|
||||
PreWrap,
|
||||
PreLine,
|
||||
PreSpace,
|
||||
enum class StyleWhiteSpaceCollapse : uint8_t {
|
||||
Collapse = 0,
|
||||
// TODO: Discard not yet supported
|
||||
Preserve,
|
||||
PreserveBreaks,
|
||||
PreserveSpaces,
|
||||
BreakSpaces,
|
||||
};
|
||||
|
||||
// See nsStyleText
|
||||
enum class StyleTextWrapMode : uint8_t {
|
||||
Wrap = 0,
|
||||
Nowrap,
|
||||
};
|
||||
|
||||
// See nsStyleText
|
||||
// TODO: this will become StyleTextWrapStyle when we turn text-wrap
|
||||
// (see https://bugzilla.mozilla.org/show_bug.cgi?id=1758391) and
|
||||
|
@ -2791,7 +2791,6 @@ nsStyleText::nsStyleText(const Document& aDocument)
|
||||
mTextAlign(StyleTextAlign::Start),
|
||||
mTextAlignLast(StyleTextAlignLast::Auto),
|
||||
mTextJustify(StyleTextJustify::Auto),
|
||||
mWhiteSpace(StyleWhiteSpace::Normal),
|
||||
mHyphens(StyleHyphens::Manual),
|
||||
mRubyAlign(StyleRubyAlign::SpaceAround),
|
||||
mRubyPosition(StyleRubyPosition::AlternateOver),
|
||||
@ -2828,7 +2827,8 @@ nsStyleText::nsStyleText(const nsStyleText& aSource)
|
||||
mTextAlign(aSource.mTextAlign),
|
||||
mTextAlignLast(aSource.mTextAlignLast),
|
||||
mTextJustify(aSource.mTextJustify),
|
||||
mWhiteSpace(aSource.mWhiteSpace),
|
||||
mWhiteSpaceCollapse(aSource.mWhiteSpaceCollapse),
|
||||
mTextWrapMode(aSource.mTextWrapMode),
|
||||
mLineBreak(aSource.mLineBreak),
|
||||
mWordBreak(aSource.mWordBreak),
|
||||
mOverflowWrap(aSource.mOverflowWrap),
|
||||
@ -2875,7 +2875,8 @@ nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aNewData) const {
|
||||
if ((mTextAlign != aNewData.mTextAlign) ||
|
||||
(mTextAlignLast != aNewData.mTextAlignLast) ||
|
||||
(mTextTransform != aNewData.mTextTransform) ||
|
||||
(mWhiteSpace != aNewData.mWhiteSpace) ||
|
||||
(mWhiteSpaceCollapse != aNewData.mWhiteSpaceCollapse) ||
|
||||
(mTextWrapMode != aNewData.mTextWrapMode) ||
|
||||
(mLineBreak != aNewData.mLineBreak) ||
|
||||
(mWordBreak != aNewData.mWordBreak) ||
|
||||
(mOverflowWrap != aNewData.mOverflowWrap) ||
|
||||
|
@ -845,7 +845,9 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText {
|
||||
mozilla::StyleTextAlign mTextAlign;
|
||||
mozilla::StyleTextAlignLast mTextAlignLast;
|
||||
mozilla::StyleTextJustify mTextJustify;
|
||||
mozilla::StyleWhiteSpace mWhiteSpace;
|
||||
mozilla::StyleWhiteSpaceCollapse mWhiteSpaceCollapse =
|
||||
mozilla::StyleWhiteSpaceCollapse::Collapse;
|
||||
mozilla::StyleTextWrapMode mTextWrapMode = mozilla::StyleTextWrapMode::Wrap;
|
||||
mozilla::StyleLineBreak mLineBreak = mozilla::StyleLineBreak::Auto;
|
||||
|
||||
private:
|
||||
@ -918,10 +920,9 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText {
|
||||
}
|
||||
|
||||
bool WhiteSpaceIsSignificant() const {
|
||||
return mWhiteSpace == mozilla::StyleWhiteSpace::Pre ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::BreakSpaces ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreSpace;
|
||||
return mWhiteSpaceCollapse != mozilla::StyleWhiteSpaceCollapse::Collapse &&
|
||||
mWhiteSpaceCollapse !=
|
||||
mozilla::StyleWhiteSpaceCollapse::PreserveBreaks;
|
||||
}
|
||||
|
||||
bool WhiteSpaceCanHangOrVisuallyCollapse() const {
|
||||
@ -930,35 +931,27 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText {
|
||||
// WhiteSpaceCanWrapStyle() &&
|
||||
// WhiteSpaceIsSignificant()
|
||||
// which simplifies to:
|
||||
return mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap;
|
||||
return mTextWrapMode == mozilla::StyleTextWrapMode::Wrap &&
|
||||
mWhiteSpaceCollapse != mozilla::StyleWhiteSpaceCollapse::BreakSpaces;
|
||||
}
|
||||
|
||||
bool NewlineIsSignificantStyle() const {
|
||||
return mWhiteSpace == mozilla::StyleWhiteSpace::Pre ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::BreakSpaces ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreLine;
|
||||
return mWhiteSpaceCollapse == mozilla::StyleWhiteSpaceCollapse::Preserve ||
|
||||
mWhiteSpaceCollapse ==
|
||||
mozilla::StyleWhiteSpaceCollapse::PreserveBreaks ||
|
||||
mWhiteSpaceCollapse == mozilla::StyleWhiteSpaceCollapse::BreakSpaces;
|
||||
}
|
||||
|
||||
bool WhiteSpaceOrNewlineIsSignificant() const {
|
||||
return mWhiteSpace == mozilla::StyleWhiteSpace::Pre ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::BreakSpaces ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreLine ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreSpace;
|
||||
return NewlineIsSignificantStyle() || WhiteSpaceIsSignificant();
|
||||
}
|
||||
|
||||
bool TabIsSignificant() const {
|
||||
return mWhiteSpace == mozilla::StyleWhiteSpace::Pre ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::BreakSpaces;
|
||||
return !WhiteSpaceCanWrapStyle() && WhiteSpaceIsSignificant();
|
||||
}
|
||||
|
||||
bool WhiteSpaceCanWrapStyle() const {
|
||||
return mWhiteSpace == mozilla::StyleWhiteSpace::Normal ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreWrap ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::BreakSpaces ||
|
||||
mWhiteSpace == mozilla::StyleWhiteSpace::PreLine;
|
||||
return mTextWrapMode == mozilla::StyleTextWrapMode::Wrap;
|
||||
}
|
||||
|
||||
bool WordCanWrapStyle() const {
|
||||
|
@ -893,8 +893,8 @@ def _remove_common_first_line_and_first_letter_properties(props, engine):
|
||||
props.remove("overflow-wrap")
|
||||
props.remove("text-align")
|
||||
props.remove("text-justify")
|
||||
props.remove("white-space")
|
||||
props.remove("text-wrap")
|
||||
props.remove("white-space-collapse")
|
||||
props.remove("text-wrap-mode")
|
||||
props.remove("word-break")
|
||||
props.remove("text-indent")
|
||||
|
||||
@ -996,11 +996,12 @@ class PropertyRestrictions:
|
||||
def placeholder(data):
|
||||
props = PropertyRestrictions.first_line(data)
|
||||
props.add("opacity")
|
||||
props.add("white-space")
|
||||
props.add("text-wrap")
|
||||
props.add("text-overflow")
|
||||
props.add("text-align")
|
||||
props.add("text-justify")
|
||||
for p in PropertyRestrictions.shorthand(data, "white-space"):
|
||||
props.add(p)
|
||||
return props
|
||||
|
||||
# https://drafts.csswg.org/css-pseudo/#marker-pseudo
|
||||
@ -1008,7 +1009,6 @@ class PropertyRestrictions:
|
||||
def marker(data):
|
||||
return set(
|
||||
[
|
||||
"white-space",
|
||||
"text-wrap",
|
||||
"color",
|
||||
"text-combine-upright",
|
||||
@ -1019,6 +1019,7 @@ class PropertyRestrictions:
|
||||
"line-height",
|
||||
"-moz-osx-font-smoothing",
|
||||
]
|
||||
+ PropertyRestrictions.shorthand(data, "white-space")
|
||||
+ PropertyRestrictions.spec(data, "css-fonts")
|
||||
+ PropertyRestrictions.spec(data, "css-animations")
|
||||
+ PropertyRestrictions.spec(data, "css-transitions")
|
||||
@ -1033,7 +1034,6 @@ class PropertyRestrictions:
|
||||
"opacity",
|
||||
"visibility",
|
||||
"text-shadow",
|
||||
"white-space",
|
||||
"text-wrap",
|
||||
"text-combine-upright",
|
||||
"ruby-position",
|
||||
@ -1045,6 +1045,7 @@ class PropertyRestrictions:
|
||||
"background-blend-mode",
|
||||
]
|
||||
+ PropertyRestrictions.shorthand(data, "text-decoration")
|
||||
+ PropertyRestrictions.shorthand(data, "white-space")
|
||||
+ PropertyRestrictions.shorthand(data, "background")
|
||||
+ PropertyRestrictions.shorthand(data, "outline")
|
||||
+ PropertyRestrictions.shorthand(data, "font")
|
||||
|
@ -149,52 +149,26 @@ ${helpers.predefined_type(
|
||||
affects="layout",
|
||||
)}
|
||||
|
||||
<%helpers:single_keyword
|
||||
name="white-space"
|
||||
values="normal pre nowrap pre-wrap pre-line"
|
||||
engines="gecko servo-2013 servo-2020",
|
||||
extra_gecko_values="break-spaces -moz-pre-space"
|
||||
gecko_enum_prefix="StyleWhiteSpace"
|
||||
needs_conversion="True"
|
||||
animation_value_type="discrete"
|
||||
spec="https://drafts.csswg.org/css-text/#propdef-white-space"
|
||||
servo_restyle_damage="rebuild_and_reflow"
|
||||
affects="layout"
|
||||
>
|
||||
% if engine in ["servo-2013", "servo-2020"]:
|
||||
impl SpecifiedValue {
|
||||
pub fn allow_wrap(&self) -> bool {
|
||||
match *self {
|
||||
SpecifiedValue::Nowrap |
|
||||
SpecifiedValue::Pre => false,
|
||||
SpecifiedValue::Normal |
|
||||
SpecifiedValue::PreWrap |
|
||||
SpecifiedValue::PreLine => true,
|
||||
}
|
||||
}
|
||||
// TODO: `white-space-collapse: discard` not yet supported
|
||||
${helpers.single_keyword(
|
||||
name="white-space-collapse",
|
||||
values="collapse preserve preserve-breaks preserve-spaces break-spaces",
|
||||
engines="gecko",
|
||||
gecko_enum_prefix="StyleWhiteSpaceCollapse",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-text-4/#propdef-white-space-collapse",
|
||||
affects="layout",
|
||||
)}
|
||||
|
||||
pub fn preserve_newlines(&self) -> bool {
|
||||
match *self {
|
||||
SpecifiedValue::Normal |
|
||||
SpecifiedValue::Nowrap => false,
|
||||
SpecifiedValue::Pre |
|
||||
SpecifiedValue::PreWrap |
|
||||
SpecifiedValue::PreLine => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preserve_spaces(&self) -> bool {
|
||||
match *self {
|
||||
SpecifiedValue::Normal |
|
||||
SpecifiedValue::Nowrap |
|
||||
SpecifiedValue::PreLine => false,
|
||||
SpecifiedValue::Pre |
|
||||
SpecifiedValue::PreWrap => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
% endif
|
||||
</%helpers:single_keyword>
|
||||
${helpers.single_keyword(
|
||||
name="text-wrap-mode",
|
||||
values="wrap nowrap",
|
||||
engines="gecko",
|
||||
gecko_enum_prefix="StyleTextWrapMode",
|
||||
animation_value_type="discrete",
|
||||
spec="https://drafts.csswg.org/css-text-4/#propdef-text-wrap-mode",
|
||||
affects="layout",
|
||||
)}
|
||||
|
||||
${helpers.predefined_type(
|
||||
"text-shadow",
|
||||
|
@ -46,6 +46,110 @@
|
||||
}
|
||||
</%helpers:shorthand>
|
||||
|
||||
<%helpers:shorthand
|
||||
name="white-space"
|
||||
engines="gecko"
|
||||
sub_properties="text-wrap-mode white-space-collapse"
|
||||
spec="https://www.w3.org/TR/css-text-4/#white-space-property"
|
||||
>
|
||||
use crate::properties::longhands::{text_wrap_mode, white_space_collapse};
|
||||
|
||||
pub fn parse_value<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Longhands, ParseError<'i>> {
|
||||
use white_space_collapse::computed_value::T as Collapse;
|
||||
use text_wrap_mode::computed_value::T as Wrap;
|
||||
|
||||
fn parse_special_shorthands<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Longhands, ParseError<'i>> {
|
||||
let (mode, collapse) = try_match_ident_ignore_ascii_case! { input,
|
||||
"normal" => (Wrap::Wrap, Collapse::Collapse),
|
||||
"pre" => (Wrap::Nowrap, Collapse::Preserve),
|
||||
"pre-wrap" => (Wrap::Wrap, Collapse::Preserve),
|
||||
"pre-line" => (Wrap::Wrap, Collapse::PreserveBreaks),
|
||||
// TODO: deprecate/remove -moz-pre-space; the white-space-collapse: preserve-spaces value
|
||||
// should serve this purpose?
|
||||
"-moz-pre-space" => (Wrap::Wrap, Collapse::PreserveSpaces),
|
||||
};
|
||||
Ok(expanded! {
|
||||
text_wrap_mode: mode,
|
||||
white_space_collapse: collapse,
|
||||
})
|
||||
}
|
||||
|
||||
if let Ok(result) = input.try_parse(parse_special_shorthands) {
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
let mut wrap = None;
|
||||
let mut collapse = None;
|
||||
|
||||
loop {
|
||||
if wrap.is_none() {
|
||||
if let Ok(value) = input.try_parse(|input| text_wrap_mode::parse(context, input)) {
|
||||
wrap = Some(value);
|
||||
continue
|
||||
}
|
||||
}
|
||||
if collapse.is_none() {
|
||||
if let Ok(value) = input.try_parse(|input| white_space_collapse::parse(context, input)) {
|
||||
collapse = Some(value);
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if wrap.is_some() || collapse.is_some() {
|
||||
Ok(expanded! {
|
||||
text_wrap_mode: unwrap_or_initial!(text_wrap_mode, wrap),
|
||||
white_space_collapse: unwrap_or_initial!(white_space_collapse, collapse),
|
||||
})
|
||||
} else {
|
||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||
use white_space_collapse::computed_value::T as Collapse;
|
||||
use text_wrap_mode::computed_value::T as Wrap;
|
||||
|
||||
match *self.text_wrap_mode {
|
||||
Wrap::Wrap => {
|
||||
match *self.white_space_collapse {
|
||||
Collapse::Collapse => return dest.write_str("normal"),
|
||||
Collapse::Preserve => return dest.write_str("pre-wrap"),
|
||||
Collapse::PreserveBreaks => return dest.write_str("pre-line"),
|
||||
Collapse::PreserveSpaces => return dest.write_str("-moz-pre-space"),
|
||||
_ => (),
|
||||
}
|
||||
},
|
||||
Wrap::Nowrap => {
|
||||
if let Collapse::Preserve = *self.white_space_collapse {
|
||||
return dest.write_str("pre");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
let mut has_value = false;
|
||||
if *self.white_space_collapse != Collapse::Collapse {
|
||||
self.white_space_collapse.to_css(dest)?;
|
||||
has_value = true;
|
||||
}
|
||||
|
||||
if *self.text_wrap_mode != Wrap::Wrap {
|
||||
if has_value {
|
||||
dest.write_char(' ')?;
|
||||
}
|
||||
self.text_wrap_mode.to_css(dest)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
</%helpers:shorthand>
|
||||
|
||||
// CSS Compatibility
|
||||
// https://compat.spec.whatwg.org/
|
||||
<%helpers:shorthand name="-webkit-text-stroke"
|
||||
|
@ -5315,7 +5315,8 @@ pub extern "C" fn Servo_DeclarationBlock_SetKeywordValue(
|
||||
ListStyleType => Box::new(longhands::list_style_type::SpecifiedValue::from_gecko_keyword(value)),
|
||||
MathStyle => longhands::math_style::SpecifiedValue::from_gecko_keyword(value),
|
||||
MozMathVariant => longhands::_moz_math_variant::SpecifiedValue::from_gecko_keyword(value),
|
||||
WhiteSpace => longhands::white_space::SpecifiedValue::from_gecko_keyword(value),
|
||||
WhiteSpaceCollapse => get_from_computed::<longhands::white_space_collapse::SpecifiedValue>(value),
|
||||
TextWrapMode => get_from_computed::<longhands::text_wrap_mode::SpecifiedValue>(value),
|
||||
CaptionSide => get_from_computed::<CaptionSide>(value),
|
||||
BorderTopStyle => get_from_computed::<BorderStyle>(value),
|
||||
BorderRightStyle => get_from_computed::<BorderStyle>(value),
|
||||
|
Loading…
x
Reference in New Issue
Block a user