зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1019555 - Treat newlines and tabs as space characters in SVG xml:space="preserve" text. r=roc
This commit is contained in:
Родитель
3fa67f89f1
Коммит
8311e3a117
|
@ -675,8 +675,7 @@ static bool IsCSSWordSpacingSpace(const nsTextFragment* aFrag,
|
|||
return !IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
|
||||
case '\r':
|
||||
case '\t': return !aStyleText->WhiteSpaceIsSignificant();
|
||||
case '\n': return !aStyleText->NewlineIsSignificant() &&
|
||||
!aStyleText->NewlineIsDiscarded();
|
||||
case '\n': return !aStyleText->NewlineIsSignificant();
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
@ -709,7 +708,7 @@ static bool IsTrimmableSpace(const nsTextFragment* aFrag, uint32_t aPos,
|
|||
case ' ': return !aStyleText->WhiteSpaceIsSignificant() &&
|
||||
!IsSpaceCombiningSequenceTail(aFrag, aPos + 1);
|
||||
case '\n': return !aStyleText->NewlineIsSignificant() &&
|
||||
!aStyleText->NewlineIsDiscarded();
|
||||
aStyleText->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_SPACE;
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\f': return !aStyleText->WhiteSpaceIsSignificant();
|
||||
|
@ -773,21 +772,6 @@ IsAllWhitespace(const nsTextFragment* aFrag, bool aAllowNewline)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsAllNewlines(const nsTextFragment* aFrag)
|
||||
{
|
||||
if (aFrag->Is2b())
|
||||
return false;
|
||||
int32_t len = aFrag->GetLength();
|
||||
const char* str = aFrag->Get1b();
|
||||
for (int32_t i = 0; i < len; ++i) {
|
||||
char ch = str[i];
|
||||
if (ch != '\n')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
CreateObserverForAnimatedGlyphs(nsTextFrame* aFrame, const nsTArray<gfxFont*>& aFonts)
|
||||
{
|
||||
|
@ -1816,16 +1800,16 @@ PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE == 1);
|
|||
PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_NOWRAP == 2);
|
||||
PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_WRAP == 3);
|
||||
PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_LINE == 4);
|
||||
PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES == 5);
|
||||
PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_PRE_SPACE == 5);
|
||||
|
||||
static const nsTextFrameUtils::CompressionMode CSSWhitespaceToCompressionMode[] =
|
||||
{
|
||||
nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // normal
|
||||
nsTextFrameUtils::COMPRESS_NONE, // pre
|
||||
nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // nowrap
|
||||
nsTextFrameUtils::COMPRESS_NONE, // pre-wrap
|
||||
nsTextFrameUtils::COMPRESS_WHITESPACE, // pre-line
|
||||
nsTextFrameUtils::DISCARD_NEWLINE // -moz-pre-discard-newlines
|
||||
nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // normal
|
||||
nsTextFrameUtils::COMPRESS_NONE, // pre
|
||||
nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, // nowrap
|
||||
nsTextFrameUtils::COMPRESS_NONE, // pre-wrap
|
||||
nsTextFrameUtils::COMPRESS_WHITESPACE, // pre-line
|
||||
nsTextFrameUtils::COMPRESS_NONE_TRANSFORM_TO_SPACE // -moz-pre-space
|
||||
};
|
||||
|
||||
gfxTextRun*
|
||||
|
@ -7159,7 +7143,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext,
|
|||
|
||||
bool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant();
|
||||
bool preformatNewlines = textStyle->NewlineIsSignificant();
|
||||
bool preformatTabs = textStyle->WhiteSpaceIsSignificant();
|
||||
bool preformatTabs = textStyle->TabIsSignificant();
|
||||
gfxFloat tabWidth = -1;
|
||||
uint32_t start =
|
||||
FindStartAfterSkippingWhitespace(&provider, aData, textStyle, &iter, flowEndInTextRun);
|
||||
|
@ -7175,8 +7159,8 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext,
|
|||
// XXXldb Shouldn't we be including the newline as part of the
|
||||
// segment that it ends rather than part of the segment that it
|
||||
// starts?
|
||||
NS_ASSERTION(preformatNewlines || textStyle->NewlineIsDiscarded(),
|
||||
"We can't be here unless newlines are hard breaks or are discarded");
|
||||
NS_ASSERTION(preformatNewlines,
|
||||
"We can't be here unless newlines are hard breaks");
|
||||
preformattedNewline = preformatNewlines && textRun->CharIsNewline(i);
|
||||
preformattedTab = preformatTabs && textRun->CharIsTab(i);
|
||||
if (!preformattedNewline && !preformattedTab) {
|
||||
|
@ -8270,8 +8254,10 @@ static char16_t TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun,
|
|||
uint32_t aSkippedOffset, char16_t aChar)
|
||||
{
|
||||
if (aChar == '\n') {
|
||||
return aStyle->NewlineIsSignificant() || aStyle->NewlineIsDiscarded() ?
|
||||
aChar : ' ';
|
||||
return aStyle->NewlineIsSignificant() ? aChar : ' ';
|
||||
}
|
||||
if (aChar == '\t') {
|
||||
return aStyle->TabIsSignificant() ? aChar : ' ';
|
||||
}
|
||||
switch (aStyle->mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
|
@ -8380,8 +8366,7 @@ nsTextFrame::IsEmpty()
|
|||
|
||||
// XXXldb Should this check compatibility mode as well???
|
||||
const nsStyleText* textStyle = StyleText();
|
||||
if (textStyle->WhiteSpaceIsSignificant() &&
|
||||
textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES) {
|
||||
if (textStyle->WhiteSpaceIsSignificant()) {
|
||||
// XXX shouldn't we return true if the length is zero?
|
||||
return false;
|
||||
}
|
||||
|
@ -8395,10 +8380,8 @@ nsTextFrame::IsEmpty()
|
|||
}
|
||||
|
||||
bool isEmpty =
|
||||
textStyle->mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES ?
|
||||
IsAllNewlines(mContent->GetText()) :
|
||||
IsAllWhitespace(mContent->GetText(),
|
||||
textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
|
||||
IsAllWhitespace(mContent->GetText(),
|
||||
textStyle->mWhiteSpace != NS_STYLE_WHITESPACE_PRE_LINE);
|
||||
mState |= (isEmpty ? TEXT_IS_ONLY_WHITESPACE : TEXT_ISNOT_ONLY_WHITESPACE);
|
||||
return isEmpty;
|
||||
}
|
||||
|
|
|
@ -47,20 +47,27 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
|
|||
bool lastCharArabic = false;
|
||||
|
||||
if (aCompression == COMPRESS_NONE ||
|
||||
aCompression == DISCARD_NEWLINE) {
|
||||
aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) {
|
||||
// Skip discardables.
|
||||
uint32_t i;
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
char16_t ch = *aText++;
|
||||
if (IsDiscardable(ch, &flags) ||
|
||||
(ch == '\n' && aCompression == DISCARD_NEWLINE)) {
|
||||
if (IsDiscardable(ch, &flags)) {
|
||||
aSkipChars->SkipChar();
|
||||
} else {
|
||||
aSkipChars->KeepChar();
|
||||
if (ch > ' ') {
|
||||
lastCharArabic = IS_ARABIC_CHAR(ch);
|
||||
} else if (ch == '\t') {
|
||||
flags |= TEXT_HAS_TAB;
|
||||
} else if (aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) {
|
||||
if (ch == '\t' || ch == '\n') {
|
||||
ch = ' ';
|
||||
flags |= TEXT_WAS_TRANSFORMED;
|
||||
}
|
||||
} else {
|
||||
// aCompression == COMPRESS_NONE
|
||||
if (ch == '\t') {
|
||||
flags |= TEXT_HAS_TAB;
|
||||
}
|
||||
}
|
||||
*aOutput++ = ch;
|
||||
}
|
||||
|
@ -147,18 +154,25 @@ nsTextFrameUtils::TransformText(const uint8_t* aText, uint32_t aLength,
|
|||
uint8_t* outputStart = aOutput;
|
||||
|
||||
if (aCompression == COMPRESS_NONE ||
|
||||
aCompression == DISCARD_NEWLINE) {
|
||||
aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) {
|
||||
// Skip discardables.
|
||||
uint32_t i;
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
uint8_t ch = *aText++;
|
||||
if (IsDiscardable(ch, &flags) ||
|
||||
(ch == '\n' && aCompression == DISCARD_NEWLINE)) {
|
||||
if (IsDiscardable(ch, &flags)) {
|
||||
aSkipChars->SkipChar();
|
||||
} else {
|
||||
aSkipChars->KeepChar();
|
||||
if (ch == '\t') {
|
||||
flags |= TEXT_HAS_TAB;
|
||||
if (aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) {
|
||||
if (ch == '\t' || ch == '\n') {
|
||||
ch = ' ';
|
||||
flags |= TEXT_WAS_TRANSFORMED;
|
||||
}
|
||||
} else {
|
||||
// aCompression == COMPRESS_NONE
|
||||
if (ch == '\t') {
|
||||
flags |= TEXT_HAS_TAB;
|
||||
}
|
||||
}
|
||||
*aOutput++ = ch;
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
COMPRESS_NONE,
|
||||
COMPRESS_WHITESPACE,
|
||||
COMPRESS_WHITESPACE_NEWLINE,
|
||||
DISCARD_NEWLINE
|
||||
COMPRESS_NONE_TRANSFORM_TO_SPACE
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
p { font: 16px monospace; white-space: pre; }
|
||||
span { background-color: lime }
|
||||
</style>
|
||||
<p><span>a b</span></p>
|
||||
<p><span>ab</span></p>
|
||||
<p><span>a b</span></p>
|
||||
<p><span> a b</span></p>
|
||||
<p><span>a </span></p>
|
||||
<p><span></span></p>
|
||||
<p><span> </span></p>
|
||||
<p><span>. </span></p>
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
p { font: 16px monospace; white-space: pre; }
|
||||
span { background-color: lime }
|
||||
</style>
|
||||
<p><span>a b</span></p>
|
||||
<p><span>a b</span></p>
|
||||
<p><span>a b</span></p>
|
||||
<p><span> a b </span></p>
|
||||
<p><span>a </span></p>
|
||||
<p><span> </span></p>
|
||||
<p><span> </span></p>
|
||||
<p><span>. </span></p>
|
||||
<p><span>a b</span></p>
|
||||
<p><span>a b</span></p>
|
||||
<p><span> a b </span></p>
|
||||
<p><span>a </span></p>
|
||||
<p><span> </span></p>
|
||||
<p><span> </span></p>
|
||||
<p><span>. </span></p>
|
|
@ -1,6 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
p { font: 16px monospace; white-space: -moz-pre-discard-newlines; }
|
||||
p { font: 16px monospace; white-space: -moz-pre-space; }
|
||||
span { background-color: lime }
|
||||
</style>
|
||||
<p><span>a b</span></p>
|
||||
|
@ -11,3 +11,10 @@ span { background-color: lime }
|
|||
<p><span>


</span></p>
|
||||
<p><span> 


 </span></p>
|
||||
<p><span>. 
</span></p>
|
||||
<p><span>a	b</span></p>
|
||||
<p><span>a 	 b</span></p>
|
||||
<p><span>	 a	 b	</span></p>
|
||||
<p><span>a </span></p>
|
||||
<p><span>			</span></p>
|
||||
<p><span> 			 </span></p>
|
||||
<p><span>. 	</span></p>
|
|
@ -29,7 +29,7 @@ fuzzy-if(Android,255,42) == pre-line-1.html pre-line-1-ref.html
|
|||
== pre-line-2.html pre-line-2-ref.html
|
||||
== pre-line-3.html pre-line-3-ref.html
|
||||
== pre-line-4.html pre-line-4-ref.html
|
||||
== pre-discard-newlines-1.html pre-discard-newlines-1-ref.html
|
||||
== pre-space-1.html pre-space-1-ref.html
|
||||
== soft-hyphens-1a.html soft-hyphens-1-ref.html
|
||||
== soft-hyphens-1b.html soft-hyphens-1-ref.html
|
||||
== soft-hyphens-1c.html soft-hyphens-1-ref.html
|
||||
|
|
|
@ -128,7 +128,7 @@ CSS_KEY(-moz-oriya, _moz_oriya)
|
|||
CSS_KEY(-moz-persian, _moz_persian)
|
||||
CSS_KEY(-moz-plaintext, _moz_plaintext)
|
||||
CSS_KEY(-moz-popup, _moz_popup)
|
||||
CSS_KEY(-moz-pre-discard-newlines, _moz_pre_discard_newlines)
|
||||
CSS_KEY(-moz-pre-space, _moz_pre_space)
|
||||
CSS_KEY(-moz-pull-down-menu, _moz_pull_down_menu)
|
||||
CSS_KEY(-moz-right, _moz_right)
|
||||
CSS_KEY(-moz-scrollbars-horizontal, _moz_scrollbars_horizontal)
|
||||
|
|
|
@ -1715,7 +1715,7 @@ const KTableValue nsCSSProps::kWhitespaceKTable[] = {
|
|||
eCSSKeyword_nowrap, NS_STYLE_WHITESPACE_NOWRAP,
|
||||
eCSSKeyword_pre_wrap, NS_STYLE_WHITESPACE_PRE_WRAP,
|
||||
eCSSKeyword_pre_line, NS_STYLE_WHITESPACE_PRE_LINE,
|
||||
eCSSKeyword__moz_pre_discard_newlines, NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES,
|
||||
eCSSKeyword__moz_pre_space, NS_STYLE_WHITESPACE_PRE_SPACE,
|
||||
eCSSKeyword_UNKNOWN,-1
|
||||
};
|
||||
|
||||
|
|
|
@ -822,7 +822,7 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) {
|
|||
#define NS_STYLE_WHITESPACE_NOWRAP 2
|
||||
#define NS_STYLE_WHITESPACE_PRE_WRAP 3
|
||||
#define NS_STYLE_WHITESPACE_PRE_LINE 4
|
||||
#define NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES 5
|
||||
#define NS_STYLE_WHITESPACE_PRE_SPACE 5
|
||||
|
||||
// See nsStyleText
|
||||
#define NS_STYLE_WORDBREAK_NORMAL 0
|
||||
|
|
|
@ -1529,7 +1529,7 @@ struct nsStyleText {
|
|||
bool WhiteSpaceIsSignificant() const {
|
||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
|
||||
}
|
||||
|
||||
bool NewlineIsSignificant() const {
|
||||
|
@ -1538,15 +1538,16 @@ struct nsStyleText {
|
|||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE;
|
||||
}
|
||||
|
||||
bool NewlineIsDiscarded() const {
|
||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
|
||||
}
|
||||
|
||||
bool WhiteSpaceOrNewlineIsSignificant() const {
|
||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP ||
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_LINE ||
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_DISCARD_NEWLINES;
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_SPACE;
|
||||
}
|
||||
|
||||
bool TabIsSignificant() const {
|
||||
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
|
||||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
|
||||
}
|
||||
|
||||
bool WhiteSpaceCanWrapStyle() const {
|
||||
|
|
|
@ -3335,7 +3335,7 @@ var gCSSProperties = {
|
|||
inherited: true,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "normal" ],
|
||||
other_values: [ "pre", "nowrap", "pre-wrap", "pre-line", "-moz-pre-discard-newlines" ],
|
||||
other_values: [ "pre", "nowrap", "pre-wrap", "pre-line", "-moz-pre-space" ],
|
||||
invalid_values: []
|
||||
},
|
||||
"widows": {
|
||||
|
|
|
@ -65,7 +65,7 @@ foreignObject {
|
|||
}
|
||||
|
||||
*[xml|space=preserve] {
|
||||
white-space: -moz-pre-discard-newlines;
|
||||
white-space: -moz-pre-space;
|
||||
}
|
||||
|
||||
*|*::-moz-svg-marker-anon-child {
|
||||
|
|
Загрузка…
Ссылка в новой задаче