author | Mirko Brodesser <mbrodesser@mozilla.com> |
Fri, 23 Aug 2019 14:00:50 +0000 | |
changeset 553586 | 60893d2dc2d52d63d1c200154bfefbf55740db0d |
parent 553585 | 4f533bb7002667afaf762c30f33a675fd8afad42 |
child 553587 | 03f0d268860463a053a72413b7e10596c97fbd88 |
push id | 2165 |
push user | ffxbld-merge |
push date | Mon, 14 Oct 2019 16:30:58 +0000 |
treeherder | mozilla-release@0eae18af659f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | hsivonen |
bugs | 1575495 |
milestone | 70.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/nsPlainTextSerializer.cpp +++ b/dom/base/nsPlainTextSerializer.cpp @@ -49,16 +49,18 @@ static const int32_t kIndentIncrementHea indent h(x+1) this many columns more than h(x) */ static const int32_t kIndentSizeList = kTabSize; // Indention of non-first lines of ul and ol static const int32_t kIndentSizeDD = kTabSize; // Indention of <dd> static const char16_t kNBSP = 160; static const char16_t kSPACE = ' '; +constexpr int32_t kNoFlags = 0; + static int32_t HeaderLevel(nsAtom* aTag); static int32_t GetUnicharWidth(char16_t ucs); static int32_t GetUnicharStringWidth(const char16_t* pwcs, int32_t n); // Someday may want to make this non-const: static const uint32_t TagStackSize = 500; static const uint32_t OLStackSize = 100; @@ -76,27 +78,56 @@ NS_INTERFACE_MAP_END NS_IMPL_CYCLE_COLLECTION(nsPlainTextSerializer, mElement) nsresult NS_NewPlainTextSerializer(nsIContentSerializer** aSerializer) { RefPtr<nsPlainTextSerializer> it = new nsPlainTextSerializer(); it.forget(aSerializer); return NS_OK; } -void nsPlainTextSerializer::CurrentLineContent::MaybeReplaceNbsps( - const int32_t aFlags) { - if (!(aFlags & nsIDocumentEncoder::OutputPersistNBSP)) { +// @param aFlags As defined in nsIDocumentEncoder.idl. +static void DetermineLineBreak(const int32_t aFlags, nsAString& aLineBreak) { + // Set the line break character: + if ((aFlags & nsIDocumentEncoder::OutputCRLineBreak) && + (aFlags & nsIDocumentEncoder::OutputLFLineBreak)) { + // Windows + aLineBreak.AssignLiteral(u"\r\n"); + } else if (aFlags & nsIDocumentEncoder::OutputCRLineBreak) { + // Mac + aLineBreak.AssignLiteral(u"\r"); + } else if (aFlags & nsIDocumentEncoder::OutputLFLineBreak) { + // Unix/DOM + aLineBreak.AssignLiteral(u"\n"); + } else { + // Platform/default + aLineBreak.AssignLiteral(NS_ULINEBREAK); + } +} + +nsPlainTextSerializer::CurrentLineContent::CurrentLineContent( + const int32_t aFlags) + : mFlags(aFlags) { + DetermineLineBreak(mFlags, mLineBreak); +} + +void nsPlainTextSerializer::CurrentLineContent::MaybeReplaceNbsps() { + if (!(mFlags & nsIDocumentEncoder::OutputPersistNBSP)) { // First, replace all nbsp characters with spaces, // which the unicode encoder won't do for us. mValue.ReplaceChar(kNBSP, kSPACE); } } +void nsPlainTextSerializer::CurrentLineContent::AppendLineBreak() { + mValue.Append(mLineBreak); +} + nsPlainTextSerializer::nsPlainTextSerializer() - : mFloatingLines(-1), + : mCurrentLineContent{kNoFlags}, + mFloatingLines(-1), mLineBreakDue(false), kSpace(NS_LITERAL_STRING(" ")) // Init of "constant" { mOutputString = nullptr; mHeadLevel = 0; mAtFirstColumn = true; mIndent = 0; mCiteQuoteLevel = 0; @@ -140,17 +171,17 @@ nsPlainTextSerializer::nsPlainTextSerial nsPlainTextSerializer::~nsPlainTextSerializer() { delete[] mTagStack; delete[] mOLStack; NS_WARNING_ASSERTION(mHeadLevel == 0, "Wrong head level!"); } NS_IMETHODIMP -nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn, +nsPlainTextSerializer::Init(const uint32_t aFlags, uint32_t aWrapColumn, const Encoding* aEncoding, bool aIsCopying, bool aIsWholeDocument, bool* aNeedsPreformatScanning) { #ifdef DEBUG // Check if the major control flags are set correctly. if (aFlags & nsIDocumentEncoder::OutputFormatFlowed) { NS_ASSERTION(aFlags & nsIDocumentEncoder::OutputFormatted, "If you want format=flowed, you must combine it with " @@ -168,32 +199,16 @@ nsPlainTextSerializer::Init(uint32_t aFl mSettings.mFlags = aFlags; mWrapColumn = aWrapColumn; // Only create a linebreaker if we will handle wrapping. if (MayWrap() && MayBreakLines()) { mLineBreaker = nsContentUtils::LineBreaker(); } - // Set the line break character: - if ((mSettings.mFlags & nsIDocumentEncoder::OutputCRLineBreak) && - (mSettings.mFlags & nsIDocumentEncoder::OutputLFLineBreak)) { - // Windows - mLineBreak.AssignLiteral("\r\n"); - } else if (mSettings.mFlags & nsIDocumentEncoder::OutputCRLineBreak) { - // Mac - mLineBreak.Assign(char16_t('\r')); - } else if (mSettings.mFlags & nsIDocumentEncoder::OutputLFLineBreak) { - // Unix/DOM - mLineBreak.Assign(char16_t('\n')); - } else { - // Platform/default - mLineBreak.AssignLiteral(NS_LINEBREAK); - } - mLineBreakDue = false; mFloatingLines = -1; mPreformattedBlockBoundary = false; if (mSettings.mFlags & nsIDocumentEncoder::OutputFormatted) { // Get some prefs that controls how we do formatted output mSettings.mStructs = Preferences::GetBool(PREF_STRUCTS, mSettings.mStructs); @@ -207,16 +222,18 @@ nsPlainTextSerializer::Init(uint32_t aFl // other places which use this serializer currently. mSettings.mWithRubyAnnotation = gAlwaysIncludeRuby || (mSettings.mFlags & nsIDocumentEncoder::OutputRubyAnnotation); // XXX We should let the caller decide whether to do this or not mSettings.mFlags &= ~nsIDocumentEncoder::OutputNoFramesContent; + mCurrentLineContent = CurrentLineContent{mSettings.mFlags}; + return NS_OK; } bool nsPlainTextSerializer::GetLastBool(const nsTArray<bool>& aStack) { uint32_t size = aStack.Length(); if (size == 0) { return false; } @@ -321,17 +338,17 @@ nsPlainTextSerializer::AppendText(nsICon int32_t offset = textstr.FindCharInSet("\n\r"); while (offset != kNotFound) { if (offset > start) { // Pass in the line DoAddText(false, Substring(textstr, start, offset - start)); } // Pass in a newline - DoAddText(true, mLineBreak); + DoAddText(); start = offset + 1; offset = textstr.FindCharInSet("\n\r", start); } // Consume the last bit of the string if there's any left if (start < length) { if (start) { @@ -955,16 +972,18 @@ bool nsPlainTextSerializer::MustSuppress // Might be nice, eventually, to output just the selected element. // Read more in bug 31994. return true; } return false; } +void nsPlainTextSerializer::DoAddText() { DoAddText(true, EmptyString()); } + void nsPlainTextSerializer::DoAddText(bool aIsLineBreak, const nsAString& aText) { // If we don't want any output, just return if (!DoOutput()) { return; } if (!aIsLineBreak) { @@ -1096,17 +1115,17 @@ void nsPlainTextSerializer::EnsureVertic * at the start of the line. */ void nsPlainTextSerializer::FlushLine() { if (!mCurrentLineContent.mValue.IsEmpty()) { if (mAtFirstColumn) { OutputQuotesAndIndent(); // XXX: Should we always do this? Bug? } - mCurrentLineContent.MaybeReplaceNbsps(mSettings.mFlags); + mCurrentLineContent.MaybeReplaceNbsps(); Output(mCurrentLineContent.mValue); mAtFirstColumn = false; mCurrentLineContent.mValue.Truncate(); mCurrentLineContent.mWidth = 0; } } void nsPlainTextSerializer::Output(nsString& aString) { @@ -1356,18 +1375,18 @@ void nsPlainTextSerializer::EndLine(bool if (mAtFirstColumn) { // If we don't have anything "real" to output we have to // make sure the indent doesn't end in a space since that // would trick a format=flowed-aware receiver. bool stripTrailingSpaces = mCurrentLineContent.mValue.IsEmpty(); OutputQuotesAndIndent(stripTrailingSpaces); } - mCurrentLineContent.mValue.Append(mLineBreak); - mCurrentLineContent.MaybeReplaceNbsps(mSettings.mFlags); + mCurrentLineContent.MaybeReplaceNbsps(); + mCurrentLineContent.AppendLineBreak(); Output(mCurrentLineContent.mValue); mCurrentLineContent.mValue.Truncate(); mCurrentLineContent.mWidth = 0; mAtFirstColumn = true; mInWhitespace = true; mLineBreakDue = false; mFloatingLines = -1; } @@ -1552,21 +1571,22 @@ void nsPlainTextSerializer::Write(const } mCurrentLineContent.mValue.Append(stringpart); if (outputQuotes) { // Note: this call messes with mAtFirstColumn OutputQuotesAndIndent(); } - mCurrentLineContent.MaybeReplaceNbsps(mSettings.mFlags); - Output(mCurrentLineContent.mValue); + mCurrentLineContent.MaybeReplaceNbsps(); if (outputLineBreak) { - Output(mLineBreak); + mCurrentLineContent.AppendLineBreak(); } + Output(mCurrentLineContent.mValue); + mAtFirstColumn = atFirstColumn; } // Reset mCurrentLineContent.mValue. mCurrentLineContent.mValue.Truncate(); #ifdef DEBUG_wrapping printf("No wrapping: newline is %d, totLen is %d\n", newline, totLen);
--- a/dom/base/nsPlainTextSerializer.h +++ b/dom/base/nsPlainTextSerializer.h @@ -104,26 +104,27 @@ class nsPlainTextSerializer final : publ * Returns the local name of the element as an atom if the element is an * HTML element and the atom is a static atom. Otherwise, nullptr is returned. */ static nsAtom* GetIdForContent(nsIContent* aContent); nsresult DoOpenContainer(nsAtom* aTag); nsresult DoCloseContainer(nsAtom* aTag); nsresult DoAddLeaf(nsAtom* aTag); + void DoAddText(); // @param aText Ignored if aIsLineBreak is true. void DoAddText(bool aIsLineBreak, const nsAString& aText); // Inlined functions - inline bool MayWrap() { + inline bool MayWrap() const { return mWrapColumn && ((mSettings.mFlags & nsIDocumentEncoder::OutputFormatted) || (mSettings.mFlags & nsIDocumentEncoder::OutputWrap)); } - inline bool MayBreakLines() { + inline bool MayBreakLines() const { return !(mSettings.mFlags & nsIDocumentEncoder::OutputDisallowLineBreaking); } inline bool DoOutput() const { return mHeadLevel == 0; } inline bool IsQuotedLine(const nsAString& aLine) { return !aLine.IsEmpty() && aLine.First() == char16_t('>'); } @@ -163,26 +164,36 @@ class nsPlainTextSerializer final : publ int32_t mFlags = 0; // Whether the output should include ruby annotations. bool mWithRubyAnnotation = false; }; Settings mSettings; + // Excludes indentation and quotes. class CurrentLineContent { public: // @param aFlags As defined in nsIDocumentEncoder.idl. - void MaybeReplaceNbsps(int32_t aFlags); + explicit CurrentLineContent(int32_t aFlags); - // Excludes indentation and quotes. + void MaybeReplaceNbsps(); + + void AppendLineBreak(); + nsString mValue; // The width of the line as it will appear on the screen (approx.). uint32_t mWidth = 0; + + private: + // As defined in nsIDocumentEncoder.idl. + int32_t mFlags; + + nsString mLineBreak; }; CurrentLineContent mCurrentLineContent; // If we've just written out a cite blockquote, we need to remember it // so we don't duplicate spaces before a <pre wrap> (which mail uses to quote // old messages). bool mHasWrittenCiteBlockquote; @@ -252,17 +263,16 @@ class nsPlainTextSerializer final : publ uint32_t mIgnoreAboveIndex; // The stack for ordered lists int32_t* mOLStack; uint32_t mOLStackIndex; uint32_t mULCount; - nsString mLineBreak; RefPtr<mozilla::intl::LineBreaker> mLineBreaker; // Conveniance constant. It would be nice to have it as a const static // variable, but that causes issues with OpenBSD and module unloading. const nsString kSpace; // mIgnoredChildNodeLevel is used to tell if current node is an ignorable // child node. The initial value of mIgnoredChildNodeLevel is 0. When
--- a/xpcom/ds/nsCRT.h +++ b/xpcom/ds/nsCRT.h @@ -9,20 +9,22 @@ #include <stdlib.h> #include <ctype.h> #include "plstr.h" #include "nscore.h" #include "nsCRTGlue.h" #if defined(XP_WIN) # define NS_LINEBREAK "\015\012" +# define NS_ULINEBREAK u"\015\012" # define NS_LINEBREAK_LEN 2 #else # ifdef XP_UNIX # define NS_LINEBREAK "\012" +# define NS_ULINEBREAK u"\012" # define NS_LINEBREAK_LEN 1 # endif /* XP_UNIX */ #endif /* XP_WIN */ extern const char16_t kIsoLatin1ToUCS2[256]; /// This is a wrapper class around all the C runtime functions.