mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-18 05:07:31 +09:00
Issue #1914 - Implement white-space: break-spaces
This also simplifies GetCSSWhitespaceToCompressionMode (FFS with the function names, Mozilla!) to be less fragile.
This commit is contained in:
parent
163bce2e81
commit
afbfbcb1e1
9 changed files with 57 additions and 37 deletions
|
|
@ -9519,6 +9519,7 @@ exports.CSS_PROPERTIES = {
|
||||||
"supports": [],
|
"supports": [],
|
||||||
"values": [
|
"values": [
|
||||||
"-moz-pre-space",
|
"-moz-pre-space",
|
||||||
|
"break-spaces",
|
||||||
"inherit",
|
"inherit",
|
||||||
"initial",
|
"initial",
|
||||||
"normal",
|
"normal",
|
||||||
|
|
|
||||||
|
|
@ -851,6 +851,7 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
|
||||||
bool *aUsedHyphenation,
|
bool *aUsedHyphenation,
|
||||||
uint32_t *aLastBreak,
|
uint32_t *aLastBreak,
|
||||||
bool aCanWordWrap,
|
bool aCanWordWrap,
|
||||||
|
bool aCanWhitespaceWrap,
|
||||||
gfxBreakPriority *aBreakPriority)
|
gfxBreakPriority *aBreakPriority)
|
||||||
{
|
{
|
||||||
aMaxLength = std::min(aMaxLength, GetLength() - aStart);
|
aMaxLength = std::min(aMaxLength, GetLength() - aStart);
|
||||||
|
|
@ -918,7 +919,15 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
|
||||||
aCanWordWrap && mCharacterGlyphs[i].IsClusterStart() &&
|
aCanWordWrap && mCharacterGlyphs[i].IsClusterStart() &&
|
||||||
*aBreakPriority <= gfxBreakPriority::eWordWrapBreak;
|
*aBreakPriority <= gfxBreakPriority::eWordWrapBreak;
|
||||||
|
|
||||||
if (atBreak || wordWrapping) {
|
bool whitespaceWrapping = false;
|
||||||
|
if (i > aStart) {
|
||||||
|
// The spec says the breaking opportunity is *after* whitespace.
|
||||||
|
auto const& g = mCharacterGlyphs[i - 1];
|
||||||
|
whitespaceWrapping = aCanWhitespaceWrap &&
|
||||||
|
(g.CharIsSpace() || g.CharIsTab() || g.CharIsNewline());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atBreak || wordWrapping || whitespaceWrapping) {
|
||||||
gfxFloat hyphenatedAdvance = advance;
|
gfxFloat hyphenatedAdvance = advance;
|
||||||
if (atHyphenationBreak) {
|
if (atHyphenationBreak) {
|
||||||
hyphenatedAdvance += aProvider->GetHyphenWidth();
|
hyphenatedAdvance += aProvider->GetHyphenWidth();
|
||||||
|
|
@ -930,8 +939,9 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
|
||||||
lastBreakTrimmableChars = trimmableChars;
|
lastBreakTrimmableChars = trimmableChars;
|
||||||
lastBreakTrimmableAdvance = trimmableAdvance;
|
lastBreakTrimmableAdvance = trimmableAdvance;
|
||||||
lastBreakUsedHyphenation = atHyphenationBreak;
|
lastBreakUsedHyphenation = atHyphenationBreak;
|
||||||
*aBreakPriority = atBreak ? gfxBreakPriority::eNormalBreak
|
*aBreakPriority = (atBreak || whitespaceWrapping)
|
||||||
: gfxBreakPriority::eWordWrapBreak;
|
? gfxBreakPriority::eNormalBreak
|
||||||
|
: gfxBreakPriority::eWordWrapBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
width += advance;
|
width += advance;
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,7 @@ public:
|
||||||
bool *aUsedHyphenation,
|
bool *aUsedHyphenation,
|
||||||
uint32_t *aLastBreak,
|
uint32_t *aLastBreak,
|
||||||
bool aCanWordWrap,
|
bool aCanWordWrap,
|
||||||
|
bool aCanWhitespaceWrap,
|
||||||
gfxBreakPriority *aBreakPriority);
|
gfxBreakPriority *aBreakPriority);
|
||||||
|
|
||||||
// Utility getters
|
// Utility getters
|
||||||
|
|
|
||||||
|
|
@ -1988,35 +1988,31 @@ GetHyphenTextRun(const gfxTextRun* aTextRun, DrawTarget* aDrawTarget,
|
||||||
MakeHyphenTextRun(dt, aTextRun->GetAppUnitsPerDevUnit());
|
MakeHyphenTextRun(dt, aTextRun->GetAppUnitsPerDevUnit());
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(NS_STYLE_WHITESPACE_NORMAL == 0, "Convention: NS_STYLE_WHITESPACE_NORMAL should be 0");
|
|
||||||
static_assert(NS_STYLE_WHITESPACE_PRE == 1, "Convention: NS_STYLE_WHITESPACE_PRE should be 1");
|
|
||||||
static_assert(NS_STYLE_WHITESPACE_NOWRAP == 2, "Convention: NS_STYLE_WHITESPACE_NOWRAP should be 2");
|
|
||||||
static_assert(NS_STYLE_WHITESPACE_PRE_WRAP == 3, "Convention: NS_STYLE_WHITESPACE_PRE_WRAP should be 3");
|
|
||||||
static_assert(NS_STYLE_WHITESPACE_PRE_LINE == 4, "Convention: NS_STYLE_WHITESPACE_PRE_LINE should be 4");
|
|
||||||
static_assert(NS_STYLE_WHITESPACE_PRE_SPACE == 5, "Convention: NS_STYLE_WHITESPACE_PRE_SPACE should be 5");
|
|
||||||
|
|
||||||
static nsTextFrameUtils::CompressionMode
|
static nsTextFrameUtils::CompressionMode
|
||||||
GetCSSWhitespaceToCompressionMode(nsTextFrame* aFrame,
|
GetCSSWhitespaceToCompressionMode(nsTextFrame* aFrame,
|
||||||
const nsStyleText* aStyleText)
|
const nsStyleText* aStyleText)
|
||||||
{
|
{
|
||||||
static const nsTextFrameUtils::CompressionMode sModes[] =
|
switch (aStyleText->mWhiteSpace) {
|
||||||
{
|
case NS_STYLE_WHITESPACE_NORMAL:
|
||||||
nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // normal
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
nsTextFrameUtils::COMPRESS_NONE, // pre
|
return nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE;
|
||||||
nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // nowrap
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
nsTextFrameUtils::COMPRESS_NONE, // pre-wrap
|
case NS_STYLE_WHITESPACE_PRE_WRAP:
|
||||||
nsTextFrameUtils::COMPRESS_WHITESPACE, // pre-line
|
case NS_STYLE_WHITESPACE_BREAK_SPACES:
|
||||||
nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE // -moz-pre-space
|
if (!aStyleText->NewlineIsSignificant(aFrame)) {
|
||||||
};
|
// If newline is set to be preserved, but then suppressed,
|
||||||
|
// transform newline to space.
|
||||||
auto compression = sModes[aStyleText->mWhiteSpace];
|
return nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE;
|
||||||
if (compression == nsTextFrameUtils::COMPRESS_NONE &&
|
}
|
||||||
!aStyleText->NewlineIsSignificant(aFrame)) {
|
return nsTextFrameUtils::COMPRESS_NONE;
|
||||||
// If newline is set to be preserved, but then suppressed,
|
case NS_STYLE_WHITESPACE_PRE_SPACE:
|
||||||
// transform newline to space.
|
return nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE;
|
||||||
compression = nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE;
|
case NS_STYLE_WHITESPACE_PRE_LINE:
|
||||||
|
return nsTextFrameUtils::COMPRESS_WHITESPACE;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Unknown white-space value");
|
||||||
|
return nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE;
|
||||||
}
|
}
|
||||||
return compression;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<gfxTextRun>
|
already_AddRefed<gfxTextRun>
|
||||||
|
|
@ -9206,8 +9202,10 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||||
}
|
}
|
||||||
bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() ||
|
bool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant() ||
|
||||||
(GetStateBits() & TEXT_IS_IN_TOKEN_MATHML);
|
(GetStateBits() & TEXT_IS_IN_TOKEN_MATHML);
|
||||||
|
bool isBreakSpaces = textStyle->mWhiteSpace == NS_STYLE_WHITESPACE_BREAK_SPACES;
|
||||||
// allow whitespace to overflow the container
|
// allow whitespace to overflow the container
|
||||||
bool whitespaceCanHang = textStyle->WhiteSpaceCanWrapStyle() &&
|
bool whitespaceCanHang = !isBreakSpaces &&
|
||||||
|
textStyle->WhiteSpaceCanWrapStyle() &&
|
||||||
textStyle->WhiteSpaceIsSignificant();
|
textStyle->WhiteSpaceIsSignificant();
|
||||||
gfxBreakPriority breakPriority = aLineLayout.LastOptionalBreakPriority();
|
gfxBreakPriority breakPriority = aLineLayout.LastOptionalBreakPriority();
|
||||||
gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak;
|
gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak;
|
||||||
|
|
@ -9227,7 +9225,9 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||||
&textMetrics, boundingBoxType,
|
&textMetrics, boundingBoxType,
|
||||||
aDrawTarget,
|
aDrawTarget,
|
||||||
&usedHyphenation, &transformedLastBreak,
|
&usedHyphenation, &transformedLastBreak,
|
||||||
textStyle->WordCanWrap(this), &breakPriority);
|
textStyle->WordCanWrap(this),
|
||||||
|
isBreakSpaces,
|
||||||
|
&breakPriority);
|
||||||
if (!length && !textMetrics.mAscent && !textMetrics.mDescent) {
|
if (!length && !textMetrics.mAscent && !textMetrics.mDescent) {
|
||||||
// If we're measuring a zero-length piece of text, update
|
// If we're measuring a zero-length piece of text, update
|
||||||
// the height manually.
|
// the height manually.
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ CSS_KEY(both, both)
|
||||||
CSS_KEY(bottom, bottom)
|
CSS_KEY(bottom, bottom)
|
||||||
CSS_KEY(bottom-outside, bottom_outside)
|
CSS_KEY(bottom-outside, bottom_outside)
|
||||||
CSS_KEY(break-all, break_all)
|
CSS_KEY(break-all, break_all)
|
||||||
|
CSS_KEY(break-spaces, break_spaces)
|
||||||
CSS_KEY(break-word, break_word)
|
CSS_KEY(break-word, break_word)
|
||||||
CSS_KEY(brightness, brightness)
|
CSS_KEY(brightness, brightness)
|
||||||
CSS_KEY(browser, browser)
|
CSS_KEY(browser, browser)
|
||||||
|
|
|
||||||
|
|
@ -2253,6 +2253,7 @@ const KTableEntry nsCSSProps::kWhitespaceKTable[] = {
|
||||||
{ eCSSKeyword_pre_wrap, NS_STYLE_WHITESPACE_PRE_WRAP },
|
{ eCSSKeyword_pre_wrap, NS_STYLE_WHITESPACE_PRE_WRAP },
|
||||||
{ eCSSKeyword_pre_line, NS_STYLE_WHITESPACE_PRE_LINE },
|
{ eCSSKeyword_pre_line, NS_STYLE_WHITESPACE_PRE_LINE },
|
||||||
{ eCSSKeyword__moz_pre_space, NS_STYLE_WHITESPACE_PRE_SPACE },
|
{ eCSSKeyword__moz_pre_space, NS_STYLE_WHITESPACE_PRE_SPACE },
|
||||||
|
{ eCSSKeyword_break_spaces, NS_STYLE_WHITESPACE_BREAK_SPACES },
|
||||||
{ eCSSKeyword_UNKNOWN, -1 }
|
{ eCSSKeyword_UNKNOWN, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -995,12 +995,13 @@ enum class StyleDisplay : uint8_t {
|
||||||
#define NS_STYLE_TABSIZE_INITIAL 8
|
#define NS_STYLE_TABSIZE_INITIAL 8
|
||||||
|
|
||||||
// See nsStyleText
|
// See nsStyleText
|
||||||
#define NS_STYLE_WHITESPACE_NORMAL 0
|
#define NS_STYLE_WHITESPACE_NORMAL 0
|
||||||
#define NS_STYLE_WHITESPACE_PRE 1
|
#define NS_STYLE_WHITESPACE_PRE 1
|
||||||
#define NS_STYLE_WHITESPACE_NOWRAP 2
|
#define NS_STYLE_WHITESPACE_NOWRAP 2
|
||||||
#define NS_STYLE_WHITESPACE_PRE_WRAP 3
|
#define NS_STYLE_WHITESPACE_PRE_WRAP 3
|
||||||
#define NS_STYLE_WHITESPACE_PRE_LINE 4
|
#define NS_STYLE_WHITESPACE_PRE_LINE 4
|
||||||
#define NS_STYLE_WHITESPACE_PRE_SPACE 5
|
#define NS_STYLE_WHITESPACE_PRE_SPACE 5
|
||||||
|
#define NS_STYLE_WHITESPACE_BREAK_SPACES 6
|
||||||
|
|
||||||
// See nsStyleText
|
// See nsStyleText
|
||||||
#define NS_STYLE_WORDBREAK_NORMAL 0
|
#define NS_STYLE_WORDBREAK_NORMAL 0
|
||||||
|
|
|
||||||
|
|
@ -2105,30 +2105,35 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
|
||||||
bool WhiteSpaceIsSignificant() const {
|
bool WhiteSpaceIsSignificant() const {
|
||||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||||
|
mWhiteSpace == NS_STYLE_WHITESPACE_BREAK_SPACES ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NewlineIsSignificantStyle() const {
|
bool NewlineIsSignificantStyle() const {
|
||||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||||
|
mWhiteSpace == NS_STYLE_WHITESPACE_BREAK_SPACES ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WhiteSpaceOrNewlineIsSignificant() const {
|
bool WhiteSpaceOrNewlineIsSignificant() const {
|
||||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||||
|
mWhiteSpace == NS_STYLE_WHITESPACE_BREAK_SPACES ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabIsSignificant() const {
|
bool TabIsSignificant() const {
|
||||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||||
|
mWhiteSpace == NS_STYLE_WHITESPACE_BREAK_SPACES;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WhiteSpaceCanWrapStyle() const {
|
bool WhiteSpaceCanWrapStyle() const {
|
||||||
return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
|
return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||||
|
mWhiteSpace == NS_STYLE_WHITESPACE_BREAK_SPACES ||
|
||||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
|
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4052,7 +4052,7 @@ var gCSSProperties = {
|
||||||
inherited: true,
|
inherited: true,
|
||||||
type: CSS_TYPE_LONGHAND,
|
type: CSS_TYPE_LONGHAND,
|
||||||
initial_values: [ "normal" ],
|
initial_values: [ "normal" ],
|
||||||
other_values: [ "pre", "nowrap", "pre-wrap", "pre-line", "-moz-pre-space" ],
|
other_values: [ "pre", "nowrap", "pre-wrap", "pre-line", "-moz-pre-space", "break-spaces" ],
|
||||||
invalid_values: []
|
invalid_values: []
|
||||||
},
|
},
|
||||||
"width": {
|
"width": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue