--- a/dom/public/idl/css/nsIDOMCSS2Properties.idl
+++ b/dom/public/idl/css/nsIDOMCSS2Properties.idl
@@ -401,17 +401,17 @@ interface nsIDOMCSS2Properties : nsISupp
attribute DOMString wordSpacing;
// raises(DOMException) on setting
attribute DOMString zIndex;
// raises(DOMException) on setting
};
-[scriptable, uuid(5d8aab68-445b-4675-8661-8d722dbcb721)]
+[scriptable, uuid(216343fe-4e61-11dd-9843-001485f1fdbb)]
interface nsIDOMNSCSS2Properties : nsIDOMCSS2Properties
{
/* Non-DOM 2 extensions */
/* Mozilla extension CSS properties */
attribute DOMString MozAppearance;
// raises(DOMException) on setting
@@ -606,9 +606,12 @@ interface nsIDOMNSCSS2Properties : nsIDO
attribute DOMString MozColumnRuleWidth;
// raises(DOMException) on setting
attribute DOMString MozColumnRuleStyle;
// raises(DOMException) on setting
attribute DOMString MozColumnRuleColor;
// raises(DOMException) on setting
+
+ attribute DOMString wordWrap;
+ // raises(DOMException) on setting
};
--- a/gfx/thebes/public/gfxFont.h
+++ b/gfx/thebes/public/gfxFont.h
@@ -915,29 +915,38 @@ public:
* @param aUsedHyphenation if non-null, records if we selected a hyphenation break
* @param aLastBreak if non-null and result is aMaxLength, we set this to
* the maximal N such that
* N < aMaxLength && line break at N && GetAdvanceWidth(aStart, N) <= aWidth
* OR N < aMaxLength && hyphen break at N && GetAdvanceWidth(aStart, N) + GetHyphenWidth() <= aWidth
* or PR_UINT32_MAX if no such N exists, where GetAdvanceWidth assumes
* the effect of
* SetLineBreaks(aStart, N, aLineBreakBefore, N < aMaxLength, aProvider)
+ *
+ * @param aCanWordWrap true if we can break between any two grapheme
+ * clusters. This is set by word-wrap: break-word
+ *
+ * @param aBreakPriority in/out the priority of the break opportunity
+ * saved in the line. If we are prioritizing break opportunities, we will
+ * not set a break with a lower priority. @see gfxBreakPriority.
*
* Note that negative advance widths are possible especially if negative
* spacing is provided.
*/
PRUint32 BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
PRBool aLineBreakBefore, gfxFloat aWidth,
PropertyProvider *aProvider,
PRBool aSuppressInitialBreak,
gfxFloat *aTrimWhitespace,
Metrics *aMetrics, PRBool aTightBoundingBox,
gfxContext *aRefContextForTightBoundingBox,
PRBool *aUsedHyphenation,
- PRUint32 *aLastBreak);
+ PRUint32 *aLastBreak,
+ PRBool aCanWordWrap,
+ gfxBreakPriority *aBreakPriority);
/**
* Update the reference context.
* XXX this is a hack. New text frame does not call this. Use only
* temporarily for old text frame.
*/
void SetContext(gfxContext *aContext) {}
--- a/gfx/thebes/public/gfxTypes.h
+++ b/gfx/thebes/public/gfxTypes.h
@@ -50,16 +50,41 @@ typedef double gfxFloat;
# define THEBES_API
#elif defined(IMPL_THEBES)
# define THEBES_API NS_EXPORT
#else
# define THEBES_API NS_IMPORT
#endif
/**
+ * Priority of a line break opportunity.
+ *
+ * eNoBreak The line has no break opportunities
+ * eWordWrapBreak The line has a break opportunity only within a word. With
+ * word-wrap: break-word we will break at this point only if
+ * there are no other break opportunities in the line.
+ * eNormalBreak The line has a break opportunity determined by the standard
+ * line-breaking algorithm.
+ *
+ * Future expansion: split eNormalBreak into multiple priorities, e.g.
+ * punctuation break and whitespace break (bug 389710).
+ * As and when we implement it, text-wrap: unrestricted will
+ * mean that priorities are ignored and all line-break
+ * opportunities are equal.
+ *
+ * @see gfxTextRun::BreakAndMeasureText
+ * @see nsLineLayout::NotifyOptionalBreakPosition
+ */
+enum gfxBreakPriority {
+ eNoBreak = 0,
+ eWordWrapBreak,
+ eNormalBreak
+};
+
+/**
* Define refcounting for Thebes. For now use the stuff from nsISupportsImpl
* even though it forces the functions to be virtual...
*/
#include "nsISupportsImpl.h"
#include "nsAutoPtr.h"
#define THEBES_INLINE_DECL_REFCOUNTING(_class) \
public: \
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -1681,17 +1681,19 @@ PRUint32
gfxTextRun::BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
PRBool aLineBreakBefore, gfxFloat aWidth,
PropertyProvider *aProvider,
PRBool aSuppressInitialBreak,
gfxFloat *aTrimWhitespace,
Metrics *aMetrics, PRBool aTightBoundingBox,
gfxContext *aRefContext,
PRBool *aUsedHyphenation,
- PRUint32 *aLastBreak)
+ PRUint32 *aLastBreak,
+ PRBool aCanWordWrap,
+ gfxBreakPriority *aBreakPriority)
{
aMaxLength = PR_MIN(aMaxLength, mCharacterCount - aStart);
NS_ASSERTION(aStart + aMaxLength <= mCharacterCount, "Substring out of range");
PRUint32 bufferStart = aStart;
PRUint32 bufferLength = PR_MIN(aMaxLength, MEASUREMENT_BUFFER_SIZE);
PropertyProvider::Spacing spacingBuffer[MEASUREMENT_BUFFER_SIZE];
@@ -1737,29 +1739,32 @@ gfxTextRun::BreakAndMeasureText(PRUint32
if (haveHyphenation) {
aProvider->GetHyphenationBreaks(bufferStart, bufferLength,
hyphenBuffer);
}
}
PRBool lineBreakHere = mCharacterGlyphs[i].CanBreakBefore() &&
(!aSuppressInitialBreak || i > aStart);
- if (lineBreakHere || (haveHyphenation && hyphenBuffer[i - bufferStart])) {
+ PRBool hyphenation = haveHyphenation && hyphenBuffer[i - bufferStart];
+ PRBool wordWrapping = aCanWordWrap && *aBreakPriority <= eWordWrapBreak;
+ if (lineBreakHere || hyphenation || wordWrapping) {
gfxFloat hyphenatedAdvance = advance;
- PRBool hyphenation = !lineBreakHere;
- if (hyphenation) {
+ if (!lineBreakHere && !wordWrapping) {
hyphenatedAdvance += aProvider->GetHyphenWidth();
}
if (lastBreak < 0 || width + hyphenatedAdvance - trimmableAdvance <= aWidth) {
// We can break here.
lastBreak = i;
lastBreakTrimmableChars = trimmableChars;
lastBreakTrimmableAdvance = trimmableAdvance;
- lastBreakUsedHyphenation = hyphenation;
+ lastBreakUsedHyphenation = !lineBreakHere && !wordWrapping;
+ *aBreakPriority = hyphenation || lineBreakHere ?
+ eNormalBreak : eWordWrapBreak;
}
width += advance;
advance = 0;
if (width - trimmableAdvance > aWidth) {
// No more text fits. Abort
aborted = PR_TRUE;
break;
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -598,16 +598,20 @@
// See nsStyleText
#define NS_STYLE_WHITESPACE_NORMAL 0
#define NS_STYLE_WHITESPACE_PRE 1
#define NS_STYLE_WHITESPACE_NOWRAP 2
#define NS_STYLE_WHITESPACE_PRE_WRAP 3
// See nsStyleText
+#define NS_STYLE_WORDWRAP_NORMAL 0
+#define NS_STYLE_WORDWRAP_BREAK_WORD 1
+
+// See nsStyleText
#define NS_STYLE_UNICODE_BIDI_NORMAL 0
#define NS_STYLE_UNICODE_BIDI_EMBED 1
#define NS_STYLE_UNICODE_BIDI_OVERRIDE 2
// See nsStyleTable (here for HTML 4.0 for now, should probably change to side flags)
#define NS_STYLE_TABLE_FRAME_NONE 0
#define NS_STYLE_TABLE_FRAME_ABOVE 1
#define NS_STYLE_TABLE_FRAME_BELOW 2
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -3226,16 +3226,17 @@ nsBlockFrame::ReflowInlineFrames(nsBlock
PRInt32 spins = 0;
#endif
LineReflowStatus lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
PRBool movedPastFloat = PR_FALSE;
do {
PRBool allowPullUp = PR_TRUE;
nsIContent* forceBreakInContent = nsnull;
PRInt32 forceBreakOffset = -1;
+ gfxBreakPriority forceBreakPriority = eNoBreak;
do {
nsSpaceManager::SavedState spaceManagerState;
aState.mReflowState.mSpaceManager->PushState(&spaceManagerState);
// Once upon a time we allocated the first 30 nsLineLayout objects
// on the stack, and then we switched to the heap. At that time
// these objects were large (1100 bytes on a 32 bit system).
// Then the nsLineLayout object was shrunk to 156 bytes by
@@ -3256,17 +3257,17 @@ nsBlockFrame::ReflowInlineFrames(nsBlock
if (LINE_REFLOW_REDO_NO_PULL == lineReflowStatus ||
LINE_REFLOW_REDO_NEXT_BAND == lineReflowStatus) {
if (lineLayout.NeedsBackup()) {
NS_ASSERTION(!forceBreakInContent, "Backing up twice; this should never be necessary");
// If there is no saved break position, then this will set
// set forceBreakInContent to null and we won't back up, which is
// correct.
- forceBreakInContent = lineLayout.GetLastOptionalBreakPosition(&forceBreakOffset);
+ forceBreakInContent = lineLayout.GetLastOptionalBreakPosition(&forceBreakOffset, &forceBreakPriority);
} else {
forceBreakInContent = nsnull;
}
// restore the space manager state
aState.mReflowState.mSpaceManager->PopState(&spaceManagerState);
// Clear out float lists
aState.mCurrentLineFloats.DeleteAll();
aState.mBelowCurrentLineFloats.DeleteAll();
@@ -3384,17 +3385,17 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
// Determine whether this is a line of placeholders for out-of-flow
// continuations
PRBool isContinuingPlaceholders = PR_FALSE;
if (impactedByFloats) {
// There is a soft break opportunity at the start of the line, because
// we can always move this line down below float(s).
- if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE)) {
+ if (aLineLayout.NotifyOptionalBreakPosition(frame->GetContent(), 0, PR_TRUE, eNormalBreak)) {
lineReflowStatus = LINE_REFLOW_REDO_NEXT_BAND;
}
}
// need to repeatedly call GetChildCount here, because the child
// count can change during the loop!
for (i = 0; LINE_REFLOW_OK == lineReflowStatus && i < aLine->GetChildCount();
i++, frame = frame->GetNextSibling()) {
@@ -3462,17 +3463,18 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
NS_WARNING("We shouldn't be backing up more than once! "
"Someone must have set a break opportunity beyond the available width, "
"even though there were better break opportunities before it");
needsBackup = PR_FALSE;
}
if (needsBackup) {
// We need to try backing up to before a text run
PRInt32 offset;
- nsIContent* breakContent = aLineLayout.GetLastOptionalBreakPosition(&offset);
+ gfxBreakPriority breakPriority;
+ nsIContent* breakContent = aLineLayout.GetLastOptionalBreakPosition(&offset, &breakPriority);
// XXX It's possible, in fact not unusual, for the break opportunity to already
// be the end of the line. We should detect that and optimize to not
// re-do the line.
if (breakContent) {
// We can back up!
lineReflowStatus = LINE_REFLOW_REDO_NO_PULL;
}
} else {
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -98,16 +98,17 @@ nsLineLayout::nsLineLayout(nsPresContext
const nsLineList::iterator* aLine)
: mPresContext(aPresContext),
mSpaceManager(aSpaceManager),
mBlockReflowState(aOuterReflowState),
mLastOptionalBreakContent(nsnull),
mForceBreakContent(nsnull),
mLastOptionalBreakContentOffset(-1),
mForceBreakContentOffset(-1),
+ mLastOptionalBreakPriority(eNoBreak),
mBlockRS(nsnull),/* XXX temporary */
mMinLineHeight(0),
mTextIndent(0)
{
NS_ASSERTION(aSpaceManager || aOuterReflowState->frame->GetType() ==
nsGkAtoms::letterFrame,
"space manager should be present");
MOZ_COUNT_CTOR(nsLineLayout);
@@ -839,18 +840,20 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
metrics.height = nscoord(0xdeadbeef);
#endif
nscoord tx = x - psd->mReflowState->mComputedBorderPadding.left;
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
mSpaceManager->Translate(tx, ty);
nsIAtom* frameType = aFrame->GetType();
PRInt32 savedOptionalBreakOffset;
+ gfxBreakPriority savedOptionalBreakPriority;
nsIContent* savedOptionalBreakContent =
- GetLastOptionalBreakPosition(&savedOptionalBreakOffset);
+ GetLastOptionalBreakPosition(&savedOptionalBreakOffset,
+ &savedOptionalBreakPriority);
rv = aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
if (NS_FAILED(rv)) {
NS_WARNING( "Reflow of frame failed in nsLineLayout" );
return rv;
}
pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
@@ -1025,30 +1028,31 @@ nsLineLayout::ReflowFrame(nsIFrame* aFra
VerticalAlignFrames(span);
}
if (!continuingTextRun) {
if (!psd->mNoWrap && (!LineIsEmpty() || placedFloat)) {
// record soft break opportunity after this content that can't be
// part of a text run. This is not a text frame so we know
// that offset PR_INT32_MAX means "after the content".
- if (NotifyOptionalBreakPosition(aFrame->GetContent(), PR_INT32_MAX, optionalBreakAfterFits)) {
+ if (NotifyOptionalBreakPosition(aFrame->GetContent(), PR_INT32_MAX, optionalBreakAfterFits, eNormalBreak)) {
// If this returns true then we are being told to actually break here.
aReflowStatus = NS_INLINE_LINE_BREAK_AFTER(aReflowStatus);
}
}
}
}
else {
PushFrame(aFrame);
aPushedFrame = PR_TRUE;
// Undo any saved break positions that the frame might have told us about,
// since we didn't end up placing it
RestoreSavedBreakPosition(savedOptionalBreakContent,
- savedOptionalBreakOffset);
+ savedOptionalBreakOffset,
+ savedOptionalBreakPriority);
}
}
else {
PushFrame(aFrame);
}
#ifdef REALLY_NOISY_REFLOW
nsFrame::IndentBy(stdout, mSpanDepth);
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -50,16 +50,17 @@
#ifndef nsLineLayout_h___
#define nsLineLayout_h___
#include "nsFrame.h"
#include "nsDeque.h"
#include "nsLineBox.h"
#include "nsBlockReflowState.h"
#include "plarena.h"
+#include "gfxTypes.h"
class nsBlockFrame;
class nsSpaceManager;
class nsPlaceholderFrame;
struct nsStyleText;
class nsLineLayout {
@@ -268,53 +269,64 @@ public:
* multiple frames, and the first frame fits on the line but the whole word
* doesn't. We look back to the last optional break position and
* reflow the whole line again, forcing a break at that position. The last
* optional break position could be in a text frame or else after a frame
* that cannot be part of a text run, so those are the positions we record.
*
* @param aFits set to true if the break position is within the available width.
*
+ * @param aPriority the priority of the break opportunity. If we are
+ * prioritizing break opportunities, we will not set a break if we have
+ * already set a break with a higher priority. @see gfxBreakPriority.
+ *
* @return PR_TRUE if we are actually reflowing with forced break position and we
* should break here
*/
PRBool NotifyOptionalBreakPosition(nsIContent* aContent, PRInt32 aOffset,
- PRBool aFits) {
+ PRBool aFits, gfxBreakPriority aPriority) {
NS_ASSERTION(!aFits || !GetFlag(LL_NEEDBACKUP),
"Shouldn't be updating the break position with a break that fits after we've already flagged an overrun");
// Remember the last break position that fits; if there was no break that fit,
// just remember the first break
- if (aFits || !mLastOptionalBreakContent) {
+ if ((aFits && aPriority >= mLastOptionalBreakPriority) ||
+ !mLastOptionalBreakContent) {
mLastOptionalBreakContent = aContent;
mLastOptionalBreakContentOffset = aOffset;
+ mLastOptionalBreakPriority = aPriority;
}
return aContent && mForceBreakContent == aContent &&
mForceBreakContentOffset == aOffset;
}
/**
* Like NotifyOptionalBreakPosition, but here it's OK for LL_NEEDBACKUP
* to be set, because the caller is merely pruning some saved break position(s)
* that are actually not feasible.
*/
- void RestoreSavedBreakPosition(nsIContent* aContent, PRInt32 aOffset) {
+ void RestoreSavedBreakPosition(nsIContent* aContent, PRInt32 aOffset,
+ gfxBreakPriority aPriority) {
mLastOptionalBreakContent = aContent;
mLastOptionalBreakContentOffset = aOffset;
+ mLastOptionalBreakPriority = aPriority;
}
/**
* Signal that no backing up will be required after all.
*/
void ClearOptionalBreakPosition() {
SetFlag(LL_NEEDBACKUP, PR_FALSE);
mLastOptionalBreakContent = nsnull;
mLastOptionalBreakContentOffset = -1;
+ mLastOptionalBreakPriority = eNoBreak;
}
// Retrieve last set optional break position. When this returns null, no
// optional break has been recorded (which means that the line can't break yet).
- nsIContent* GetLastOptionalBreakPosition(PRInt32* aOffset) {
+ nsIContent* GetLastOptionalBreakPosition(PRInt32* aOffset,
+ gfxBreakPriority* aPriority) {
*aOffset = mLastOptionalBreakContentOffset;
+ *aPriority = mLastOptionalBreakPriority;
return mLastOptionalBreakContent;
}
/**
* Check whether frames overflowed the available width and CanPlaceFrame
* requested backing up to a saved break position.
*/
PRBool NeedsBackup() { return GetFlag(LL_NEEDBACKUP); }
@@ -364,16 +376,17 @@ protected:
nsSpaceManager* mSpaceManager;
const nsStyleText* mStyleText; // for the block
const nsHTMLReflowState* mBlockReflowState;
nsIContent* mLastOptionalBreakContent;
nsIContent* mForceBreakContent;
PRInt32 mLastOptionalBreakContentOffset;
PRInt32 mForceBreakContentOffset;
+ gfxBreakPriority mLastOptionalBreakPriority;
// XXX remove this when landing bug 154892 (splitting absolute positioned frames)
friend class nsInlineFrame;
nsBlockReflowState* mBlockRS;/* XXX hack! */
nscoord mMinLineHeight;
PRUint8 mTextAlign;
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -5622,24 +5622,28 @@ nsTextFrame::Reflow(nsPresContext*
iter.SetOriginalOffset(offset + limitLength);
transformedLength = iter.GetSkippedOffset() - transformedOffset;
}
PRUint32 transformedLastBreak = 0;
PRBool usedHyphenation;
gfxFloat trimmedWidth = 0;
gfxFloat availWidth = aReflowState.availableWidth;
PRBool canTrimTrailingWhitespace = !textStyle->WhiteSpaceIsSignificant();
+ PRInt32 unusedOffset;
+ gfxBreakPriority breakPriority;
+ lineLayout.GetLastOptionalBreakPosition(&unusedOffset, &breakPriority);
PRUint32 transformedCharsFit =
mTextRun->BreakAndMeasureText(transformedOffset, transformedLength,
(GetStateBits() & TEXT_START_OF_LINE) != 0,
availWidth,
&provider, !lineLayout.LineIsBreakable(),
canTrimTrailingWhitespace ? &trimmedWidth : nsnull,
&textMetrics, needTightBoundingBox, ctx,
- &usedHyphenation, &transformedLastBreak);
+ &usedHyphenation, &transformedLastBreak,
+ textStyle->WordCanWrap(), &breakPriority);
// The "end" iterator points to the first character after the string mapped
// by this frame. Basically, its original-string offset is offset+charsFit
// after we've computed charsFit.
gfxSkipCharsIterator end(provider.GetEndHint());
end.SetSkippedOffset(transformedOffset + transformedCharsFit);
PRInt32 charsFit = end.GetOriginalOffset() - offset;
if (offset + charsFit == newLineOffset) {
// We broke before a trailing preformatted '\n'. The newline should
@@ -5704,17 +5708,17 @@ nsTextFrame::Reflow(nsPresContext*
}
}
if (!brokeText && lastBreak >= 0) {
// Since everything fit and no break was forced,
// record the last break opportunity
NS_ASSERTION(textMetrics.mAdvanceWidth - trimmableWidth <= aReflowState.availableWidth,
"If the text doesn't fit, and we have a break opportunity, why didn't MeasureText use it?");
- lineLayout.NotifyOptionalBreakPosition(mContent, lastBreak, PR_TRUE);
+ lineLayout.NotifyOptionalBreakPosition(mContent, lastBreak, PR_TRUE, breakPriority);
}
PRInt32 contentLength = offset + charsFit - GetContentOffset();
/////////////////////////////////////////////////////////////////////
// Compute output metrics
/////////////////////////////////////////////////////////////////////
@@ -5773,34 +5777,36 @@ nsTextFrame::Reflow(nsPresContext*
if (transformedCharsFit > 0) {
lineLayout.SetTrimmableWidth(NSToCoordFloor(trimmableWidth));
AddStateBits(TEXT_HAS_NONCOLLAPSED_CHARACTERS);
}
if (charsFit > 0 && charsFit == length &&
HasSoftHyphenBefore(frag, mTextRun, offset, end)) {
// Record a potential break after final soft hyphen
lineLayout.NotifyOptionalBreakPosition(mContent, offset + length,
- textMetrics.mAdvanceWidth + provider.GetHyphenWidth() <= availWidth);
+ textMetrics.mAdvanceWidth + provider.GetHyphenWidth() <= availWidth,
+ eNormalBreak);
}
PRBool breakAfter = forceBreakAfter;
if (!breakAfter && charsFit == length &&
transformedOffset + transformedLength == mTextRun->GetLength() &&
(mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK)) {
// We placed all the text in the textrun and we have a break opportunity at
// the end of the textrun. We need to record it because the following
// content may not care about nsLineBreaker.
// Note that because we didn't break, we can be sure that (thanks to the
// code up above) textMetrics.mAdvanceWidth includes the width of any
// trailing whitespace. So we need to subtract trimmableWidth here
// because if we did break at this point, that much width would be trimmed.
if (textMetrics.mAdvanceWidth - trimmableWidth > availWidth) {
breakAfter = PR_TRUE;
} else {
- lineLayout.NotifyOptionalBreakPosition(mContent, offset + length, PR_TRUE);
+ lineLayout.NotifyOptionalBreakPosition(mContent, offset + length, PR_TRUE,
+ eNormalBreak);
}
}
if (completedFirstLetter) {
lineLayout.SetFirstLetterStyleOK(PR_FALSE);
}
// Compute reflow status
aStatus = contentLength == maxContentLength
--- a/layout/reftests/text/reftest.list
+++ b/layout/reftests/text/reftest.list
@@ -1,11 +1,17 @@
== long-1.html long-ref.html
random == soft-hyphens-1a.html soft-hyphens-1-ref.html # bug 406299
random == soft-hyphens-1b.html soft-hyphens-1-ref.html # bug 406299
random == soft-hyphens-1c.html soft-hyphens-1-ref.html # bug 406299
== white-space-1a.html white-space-1-ref.html
== white-space-1b.html white-space-1-ref.html
== white-space-2.html white-space-2-ref.html
+== wordwrap-01.html wordwrap-01-ref.html
+== wordwrap-02.html wordwrap-02-ref.html
+== wordwrap-03.html wordwrap-03-ref.html
+== wordwrap-04.html wordwrap-04-ref.html
+== wordwrap-05.html wordwrap-05-ref.html
+== wordwrap-06.html wordwrap-06-ref.html
== zwnj-01.html zwnj-01-ref.html
== zwnj-02.html zwnj-02-ref.html
random-if(MOZ_WIDGET_TOOLKIT=="gtk2") != zwnj-01.html zwnj-02-ref.html # Bad fonts on the tinderbox -- works locally
random == 444656.html 444656-ref.html # bug 406299
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-01-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+textarea { overflow: scroll; }
+ </style>
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <textarea rows="10" cols="20">It's
+lipsmackinthirstquen
+chinacetastinmotivat
+ingoodbuzzincooltalk
+inhighwalkinfastlivi
+nevergivincoolfizzin
+ Firefox!</textarea>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-01.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+textarea { overflow: scroll; }
+ </style>
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <textarea rows="10" cols="20">It's lipsmackinthirstquenchinacetastinmotivatingoodbuzzincooltalkinhighwalkinfastlivinevergivincoolfizzin Firefox!</textarea>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-02-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!-- tests that Arabic characters shape across word breaks -->
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+textarea { overflow: scroll; }
+ </style>
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <textarea rows="10" cols="20" dir="rtl">ذهعقروبلجيكا،الموسوع‍
+‍ةكل,تمبوابةاقتصاديةه‍
+‍ذه.ضمنهاالروسوحرمانب‍
+‍لعدد,يكنجسيمةلإعادةلم
+‍.يكنوالحلفاءبالقنابل‍
+‍هو,بحثخسائرالدفاعبال‍
+‍هجومعن.فرنسيةمارشالب‍
+‍ينيتودحرثم,وصلبشريةا
+لرايخبالحربتم.</textarea>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-02.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!-- tests that Arabic characters shape across word breaks -->
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+textarea { overflow: scroll; }
+ </style>
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <textarea rows="10" cols="20" dir="rtl">ذهعقروبلجيكا،الموسوعةكل,تمبوابةاقتصاديةهذه.ضمنهاالروسوحرمانبلعدد,يكنجسيمةلإعادةلم.يكنوالحلفاءبالقنابلهو,بحثخسائرالدفاعبالهجومعن.فرنسيةمارشالبينيتودحرثم,وصلبشريةالرايخبالحربتم.</textarea>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-03-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<!-- tests that words don't break in mid-cluster -->
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+textarea { overflow: scroll; }
+ </style>
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <textarea rows="10" cols="27">It's
+lipsmackinthirstquenchinacè
+tastinmotivatingoodbuzzincó
+oltalkinhighwalkinfastliviñ
+evergivincoolfizzin
+Firefox!</textarea>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-03.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<!-- tests that words don't break in mid-cluster -->
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <style type="text/css">
+textarea { overflow: scroll; }
+ </style>
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <textarea rows="10" cols="27">It's lipsmackinthirstquenchinacètastinmotivatingoodbuzzincóoltalkinhighwalkinfastliviñevergivincoolfizzin Firefox!</textarea>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-04-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <p style="width: 100px; word-wrap: break-word;">It's lipsmackinthirstquenchinacetastinmotivatingoodbuzzincooltalkinhighwalkinfastlivinevergivincoolfizzin Firefox!</p>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-04.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!-- Test setting word-wrap: break-word dynamically -->
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>Test Wordwrap</title>
+ <script type="text/javascript">
+function SwapStyle()
+{
+ par = document.getElementById("pp");
+ par.style.wordWrap = "break-word";
+}
+ </script>
+ </head>
+ <body onload="SwapStyle()">
+ <p id="pp" style="width: 100px; word-wrap: normal;">It's lipsmackinthirstquenchinacetastinmotivatingoodbuzzincooltalkinhighwalkinfastlivinevergivincoolfizzin Firefox!</p>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-05-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>Test Wordwrap</title>
+ </head>
+ <body>
+ <p style="width: 100px;">It's lipsmackinthirstquenchinacetastinmotivatingoodbuzzincooltalkinhighwalkinfastlivinevergivincoolfizzin Firefox!</p>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-05.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<!-- Test unsetting word-wrap: break-word dynamically -->
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>Test Wordwrap</title>
+ <script type="text/javascript">
+function SwapStyle()
+{
+ par = document.getElementById("pp");
+ par.style.wordWrap = "normal";
+}
+ </script>
+ </head>
+ <body onload="SwapStyle()">
+ <p id="pp" style="width: 100px; word-wrap: break-word;">It's lipsmackinthirstquenchinacetastinmotivatingoodbuzzincooltalkinhighwalkinfastlivinevergivincoolfizzin Firefox!</p>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-06-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>http://www.mozilla.org/projects/minefield/</title>
+ <style type="text/css">
+#viewsource {
+ font-family: -moz-fixed;
+ font-weight: normal;
+ font-size: 16px;
+ color: black;
+ white-space: pre;
+}
+pre {
+ font: inherit;
+ color: inherit;
+ white-space: inherit;
+ margin: 0;
+ width: 475px;
+}
+.attribute-name {
+ color: black;
+ font-weight: bold;
+}
+.attribute-value {
+ color: blue;
+ font-weight: normal;
+}
+ </style>
+ </head>
+ <body id="viewsource">
+ <pre id="line1"><span class="attribute-name">href</span>=<span class="attribute-value">"../../css/cavendish/content.css" </span>
+<span class="attribute-name">title</span>=<span class="attribute-value">"Cavendish"</span></pre>
+ </body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-06.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+ <title>http://www.mozilla.org/projects/minefield/</title>
+ <style type="text/css">
+#viewsource {
+ font-family: -moz-fixed;
+ font-weight: normal;
+ font-size: 16px;
+ color: black;
+ white-space: pre;
+}
+#viewsource.wrap {
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+pre {
+ font: inherit;
+ color: inherit;
+ white-space: inherit;
+ margin: 0;
+ width: 475px;
+}
+.attribute-name {
+ color: black;
+ font-weight: bold;
+}
+.attribute-value {
+ color: blue;
+ font-weight: normal;
+}
+ </style>
+ </head>
+ <body id="viewsource" class="wrap">
+ <pre id="line1"><span class="attribute-name">href</span>=<span class="attribute-value">"../../css/cavendish/content.css" </span><span class="attribute-name">title</span>=<span class="attribute-value">"Cavendish"</span></pre>
+ </body>
+</html>
\ No newline at end of file
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -121,16 +121,17 @@ textarea {
letter-spacing: normal;
vertical-align: text-bottom;
cursor: text;
-moz-binding: url("chrome://global/content/platformHTMLBindings.xml#textAreas");
-moz-appearance: textfield-multiline;
text-indent: 0;
-moz-user-select: text;
text-shadow: none;
+ word-wrap: break-word !important;
}
textarea > scrollbar {
cursor: default;
}
textarea > .anonymous-div,
input > .anonymous-div {
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -209,16 +209,17 @@ CSS_KEY(block-axis, block_axis)
CSS_KEY(bold, bold)
CSS_KEY(bolder, bolder)
CSS_KEY(border, border)
CSS_KEY(border-box, border_box)
CSS_KEY(both, both)
CSS_KEY(bottom, bottom)
CSS_KEY(bottom-outside, bottom_outside)
CSS_KEY(bounding-box, bounding_box)
+CSS_KEY(break-word, break_word)
CSS_KEY(button, button)
CSS_KEY(buttonface, buttonface)
CSS_KEY(buttonhighlight, buttonhighlight)
CSS_KEY(buttonshadow, buttonshadow)
CSS_KEY(buttontext, buttontext)
CSS_KEY(capitalize, capitalize)
CSS_KEY(caption, caption)
CSS_KEY(captiontext, captiontext)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -5178,16 +5178,19 @@ PRBool CSSParserImpl::ParseSingleValuePr
case eCSSProperty_voice_family:
return ParseFamily(aErrorCode, aValue);
case eCSSProperty_volume:
return ParseVariant(aErrorCode, aValue, VARIANT_HPN | VARIANT_KEYWORD,
nsCSSProps::kVolumeKTable);
case eCSSProperty_white_space:
return ParseVariant(aErrorCode, aValue, VARIANT_HMK,
nsCSSProps::kWhitespaceKTable);
+ case eCSSProperty_word_wrap:
+ return ParseVariant(aErrorCode, aValue, VARIANT_HMK,
+ nsCSSProps::kWordwrapKTable);
case eCSSProperty_z_index:
return ParseVariant(aErrorCode, aValue, VARIANT_AHI, nsnull);
}
// explicitly do NOT have a default case to let the compiler
// help find missing properties
return PR_FALSE;
}
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -509,16 +509,17 @@ CSS_PROP_UIRESET(-moz-user-select, user_
CSS_PROP_TEXTRESET(vertical-align, vertical_align, VerticalAlign, Text, mVerticalAlign, eCSSType_Value, kVerticalAlignKTable)
CSS_PROP_VISIBILITY(visibility, visibility, Visibility, Display, mVisibility, eCSSType_Value, kVisibilityKTable) // reflow for collapse
CSS_PROP_BACKENDONLY(voice-family, voice_family, VoiceFamily, Aural, mVoiceFamily, eCSSType_Value, nsnull)
CSS_PROP_BACKENDONLY(volume, volume, Volume, Aural, mVolume, eCSSType_Value, kVolumeKTable)
CSS_PROP_TEXT(white-space, white_space, WhiteSpace, Text, mWhiteSpace, eCSSType_Value, kWhitespaceKTable)
CSS_PROP_BACKENDONLY(widows, widows, Widows, Breaks, mWidows, eCSSType_Value, nsnull)
CSS_PROP_POSITION(width, width, Width, Position, mWidth, eCSSType_Value, kWidthKTable)
CSS_PROP_TEXT(word-spacing, word_spacing, WordSpacing, Text, mWordSpacing, eCSSType_Value, nsnull)
+CSS_PROP_TEXT(word-wrap, word_wrap, WordWrap, Text, mWordWrap, eCSSType_Value, kWordwrapKTable)
CSS_PROP_POSITION(z-index, z_index, ZIndex, Position, mZIndex, eCSSType_Value, nsnull)
CSS_PROP_XUL(-moz-box-align, box_align, MozBoxAlign, XUL, mBoxAlign, eCSSType_Value, kBoxAlignKTable) // XXX bug 3935
CSS_PROP_XUL(-moz-box-direction, box_direction, MozBoxDirection, XUL, mBoxDirection, eCSSType_Value, kBoxDirectionKTable) // XXX bug 3935
CSS_PROP_XUL(-moz-box-flex, box_flex, MozBoxFlex, XUL, mBoxFlex, eCSSType_Value, nsnull) // XXX bug 3935
CSS_PROP_XUL(-moz-box-orient, box_orient, MozBoxOrient, XUL, mBoxOrient, eCSSType_Value, kBoxOrientKTable) // XXX bug 3935
CSS_PROP_XUL(-moz-box-pack, box_pack, MozBoxPack, XUL, mBoxPack, eCSSType_Value, kBoxPackKTable) // XXX bug 3935
CSS_PROP_XUL(-moz-box-ordinal-group, box_ordinal_group, MozBoxOrdinalGroup, XUL, mBoxOrdinal, eCSSType_Value, nsnull)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -987,16 +987,22 @@ const PRInt32 nsCSSProps::kWhitespaceKTa
const PRInt32 nsCSSProps::kWidthKTable[] = {
eCSSKeyword__moz_max_content, NS_STYLE_WIDTH_MAX_CONTENT,
eCSSKeyword__moz_min_content, NS_STYLE_WIDTH_MIN_CONTENT,
eCSSKeyword__moz_fit_content, NS_STYLE_WIDTH_FIT_CONTENT,
eCSSKeyword__moz_available, NS_STYLE_WIDTH_AVAILABLE,
eCSSKeyword_UNKNOWN,-1
};
+const PRInt32 nsCSSProps::kWordwrapKTable[] = {
+ eCSSKeyword_normal, NS_STYLE_WORDWRAP_NORMAL,
+ eCSSKeyword_break_word, NS_STYLE_WORDWRAP_BREAK_WORD,
+ eCSSKeyword_UNKNOWN,-1
+};
+
// Specific keyword tables for XUL.properties
const PRInt32 nsCSSProps::kBoxAlignKTable[] = {
eCSSKeyword_stretch, NS_STYLE_BOX_ALIGN_STRETCH,
eCSSKeyword_start, NS_STYLE_BOX_ALIGN_START,
eCSSKeyword_center, NS_STYLE_BOX_ALIGN_CENTER,
eCSSKeyword_baseline, NS_STYLE_BOX_ALIGN_BASELINE,
eCSSKeyword_end, NS_STYLE_BOX_ALIGN_END,
eCSSKeyword_UNKNOWN,-1
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -188,11 +188,12 @@ public:
static const PRInt32 kUserInputKTable[];
static const PRInt32 kUserModifyKTable[];
static const PRInt32 kUserSelectKTable[];
static const PRInt32 kVerticalAlignKTable[];
static const PRInt32 kVisibilityKTable[];
static const PRInt32 kVolumeKTable[];
static const PRInt32 kWhitespaceKTable[];
static const PRInt32 kWidthKTable[]; // also min-width, max-width
+ static const PRInt32 kWordwrapKTable[];
};
#endif /* nsCSSProps_h___ */
--- a/layout/style/nsCSSStruct.h
+++ b/layout/style/nsCSSStruct.h
@@ -260,16 +260,17 @@ struct nsCSSText : public nsCSSStruct {
nsCSSValue mTextTransform;
nsCSSValue mTextAlign;
nsCSSValue mTextIndent;
nsCSSValue mDecoration;
nsCSSValueList* mTextShadow; // NEW
nsCSSValue mUnicodeBidi; // NEW
nsCSSValue mLineHeight;
nsCSSValue mWhiteSpace;
+ nsCSSValue mWordWrap;
private:
nsCSSText(const nsCSSText& aOther); // NOT IMPLEMENTED
};
struct nsRuleDataText : public nsCSSText {
nsRuleDataText() {}
private:
nsRuleDataText(const nsRuleDataText& aOther); // NOT IMPLEMENTED
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1993,16 +1993,36 @@ nsComputedDOMStyle::GetWhiteSpace(nsIDOM
} else {
val->SetIdent(nsGkAtoms::normal);
}
return CallQueryInterface(val, aValue);
}
nsresult
+nsComputedDOMStyle::GetWordWrap(nsIDOMCSSValue** aValue)
+{
+ nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
+ NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
+
+ const nsStyleText *text = GetStyleText();
+
+ if (text->mWordWrap != NS_STYLE_WORDWRAP_NORMAL) {
+ const nsAFlatCString& wordWrap =
+ nsCSSProps::ValueToKeyword(text->mWordWrap,
+ nsCSSProps::kWordwrapKTable);
+ val->SetIdent(wordWrap);
+ } else {
+ val->SetIdent(nsGkAtoms::normal);
+ }
+
+ return CallQueryInterface(val, aValue);
+}
+
+nsresult
nsComputedDOMStyle::GetVisibility(nsIDOMCSSValue** aValue)
{
nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
const nsAFlatCString& value=
nsCSSProps::ValueToKeyword(GetStyleVisibility()->mVisible,
nsCSSProps::kVisibilityKTable);
@@ -4008,17 +4028,18 @@ nsComputedDOMStyle::GetQueryableProperty
COMPUTED_STYLE_MAP_ENTRY(_moz_outline_radius_bottomLeft, OutlineRadiusBottomLeft),
COMPUTED_STYLE_MAP_ENTRY(_moz_outline_radius_bottomRight,OutlineRadiusBottomRight),
COMPUTED_STYLE_MAP_ENTRY(_moz_outline_radius_topLeft, OutlineRadiusTopLeft),
COMPUTED_STYLE_MAP_ENTRY(_moz_outline_radius_topRight, OutlineRadiusTopRight),
COMPUTED_STYLE_MAP_ENTRY(stack_sizing, StackSizing),
COMPUTED_STYLE_MAP_ENTRY(user_focus, UserFocus),
COMPUTED_STYLE_MAP_ENTRY(user_input, UserInput),
COMPUTED_STYLE_MAP_ENTRY(user_modify, UserModify),
- COMPUTED_STYLE_MAP_ENTRY(user_select, UserSelect)
+ COMPUTED_STYLE_MAP_ENTRY(user_select, UserSelect),
+ COMPUTED_STYLE_MAP_ENTRY(word_wrap, WordWrap)
#ifdef MOZ_SVG
,
COMPUTED_STYLE_MAP_ENTRY(clip_path, ClipPath),
COMPUTED_STYLE_MAP_ENTRY(clip_rule, ClipRule),
COMPUTED_STYLE_MAP_ENTRY(color_interpolation, ColorInterpolation),
COMPUTED_STYLE_MAP_ENTRY(color_interpolation_filters, ColorInterpolationFilters),
COMPUTED_STYLE_MAP_ENTRY(dominant_baseline, DominantBaseline),
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -244,16 +244,17 @@ private:
nsresult GetTextAlign(nsIDOMCSSValue** aValue);
nsresult GetTextDecoration(nsIDOMCSSValue** aValue);
nsresult GetTextIndent(nsIDOMCSSValue** aValue);
nsresult GetTextTransform(nsIDOMCSSValue** aValue);
nsresult GetTextShadow(nsIDOMCSSValue** aValue);
nsresult GetLetterSpacing(nsIDOMCSSValue** aValue);
nsresult GetWordSpacing(nsIDOMCSSValue** aValue);
nsresult GetWhiteSpace(nsIDOMCSSValue** aValue);
+ nsresult GetWordWrap(nsIDOMCSSValue** aValue);
/* Visibility properties */
nsresult GetOpacity(nsIDOMCSSValue** aValue);
nsresult GetVisibility(nsIDOMCSSValue** aValue);
/* Direction properties */
nsresult GetDirection(nsIDOMCSSValue** aValue);
nsresult GetUnicodeBidi(nsIDOMCSSValue** aValue);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2795,16 +2795,29 @@ nsRuleNode::ComputeTextData(void* aStart
text->mWhiteSpace = parentText->mWhiteSpace;
}
// word-spacing: normal, length, inherit
SetCoord(textData.mWordSpacing, text->mWordSpacing, parentText->mWordSpacing,
SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL,
aContext, mPresContext, inherited);
+ // word-wrap: enum, normal, inherit
+ if (eCSSUnit_Enumerated == textData.mWordWrap.GetUnit()) {
+ text->mWordWrap = textData.mWordWrap.GetIntValue();
+ }
+ else if (eCSSUnit_Normal == textData.mWordWrap.GetUnit() ||
+ eCSSUnit_Initial == textData.mWordWrap.GetUnit()) {
+ text->mWordWrap = NS_STYLE_WORDWRAP_NORMAL;
+ }
+ else if (eCSSUnit_Inherit == textData.mWordWrap.GetUnit()) {
+ inherited = PR_TRUE;
+ text->mWordWrap = parentText->mWordWrap;
+ }
+
COMPUTE_END_INHERITED(Text, text)
}
const void*
nsRuleNode::ComputeTextResetData(void* aStartStruct,
const nsRuleDataStruct& aData,
nsStyleContext* aContext,
nsRuleNode* aHighestNode,
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -689,20 +689,21 @@ void nsStyleContext::DumpRegressionData(
fprintf(out, "%d ", (int)pos->mBoxSizing);
pos->mZIndex.ToString(str);
fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
fprintf(out, "\" />\n");
// TEXT
IndentBy(out,aIndent);
const nsStyleText* text = GetStyleText();
- fprintf(out, "<text data=\"%d %d %d ",
+ fprintf(out, "<text data=\"%d %d %d %d",
(int)text->mTextAlign,
(int)text->mTextTransform,
- (int)text->mWhiteSpace);
+ (int)text->mWhiteSpace,
+ (int)text->mWordWrap);
text->mLetterSpacing.ToString(str);
fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
text->mLineHeight.ToString(str);
fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
text->mTextIndent.ToString(str);
fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
text->mWordSpacing.ToString(str);
fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1638,43 +1638,46 @@ CalcShadowDifference(nsCSSShadowArray* l
// nsStyleText
//
nsStyleText::nsStyleText(void)
{
mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
+ mWordWrap = NS_STYLE_WORDWRAP_NORMAL;
mLetterSpacing.SetNormalValue();
mLineHeight.SetNormalValue();
mTextIndent.SetCoordValue(0);
mWordSpacing.SetNormalValue();
mTextShadow = nsnull;
}
nsStyleText::nsStyleText(const nsStyleText& aSource)
: mTextAlign(aSource.mTextAlign),
mTextTransform(aSource.mTextTransform),
mWhiteSpace(aSource.mWhiteSpace),
+ mWordWrap(aSource.mWordWrap),
mLetterSpacing(aSource.mLetterSpacing),
mLineHeight(aSource.mLineHeight),
mTextIndent(aSource.mTextIndent),
mWordSpacing(aSource.mWordSpacing),
mTextShadow(aSource.mTextShadow)
{ }
nsStyleText::~nsStyleText(void) { }
nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
{
if ((mTextAlign != aOther.mTextAlign) ||
(mTextTransform != aOther.mTextTransform) ||
(mWhiteSpace != aOther.mWhiteSpace) ||
+ (mWordWrap != aOther.mWordWrap) ||
(mLetterSpacing != aOther.mLetterSpacing) ||
(mLineHeight != aOther.mLineHeight) ||
(mTextIndent != aOther.mTextIndent) ||
(mWordSpacing != aOther.mWordSpacing))
return NS_STYLE_HINT_REFLOW;
return CalcShadowDifference(mTextShadow, aOther.mTextShadow);
}
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -801,16 +801,17 @@ struct nsStyleText {
nsChangeHint CalcDifference(const nsStyleText& aOther) const;
#ifdef DEBUG
static nsChangeHint MaxDifference();
#endif
PRUint8 mTextAlign; // [inherited] see nsStyleConsts.h
PRUint8 mTextTransform; // [inherited] see nsStyleConsts.h
PRUint8 mWhiteSpace; // [inherited] see nsStyleConsts.h
+ PRUint8 mWordWrap; // [inherited] see nsStyleConsts.h
nsStyleCoord mLetterSpacing; // [inherited]
nsStyleCoord mLineHeight; // [inherited]
nsStyleCoord mTextIndent; // [inherited]
nsStyleCoord mWordSpacing; // [inherited]
nsRefPtr<nsCSSShadowArray> mTextShadow; // [inherited] NULL in case of a zero-length
@@ -818,16 +819,20 @@ struct nsStyleText {
return mWhiteSpace == NS_STYLE_WHITESPACE_PRE ||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
}
PRBool WhiteSpaceCanWrap() const {
return mWhiteSpace == NS_STYLE_WHITESPACE_NORMAL ||
mWhiteSpace == NS_STYLE_WHITESPACE_PRE_WRAP;
}
+
+ PRBool WordCanWrap() const {
+ return mWordWrap == NS_STYLE_WORDWRAP_BREAK_WORD;
+ }
};
struct nsStyleVisibility {
nsStyleVisibility(nsPresContext* aPresContext);
nsStyleVisibility(const nsStyleVisibility& aVisibility);
~nsStyleVisibility() {}
void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1662,16 +1662,24 @@ var gCSSProperties = {
"word-spacing": {
domProp: "wordSpacing",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "normal", "0", "0px", "-0em" ],
other_values: [ "1em", "2px", "-3px" ],
invalid_values: []
},
+ "word-wrap": {
+ domProp: "wordWrap",
+ inherited: true,
+ type: CSS_TYPE_LONGHAND,
+ initial_values: [ "normal" ],
+ other_values: [ "break-word" ],
+ invalid_values: []
+ },
"z-index": {
domProp: "zIndex",
inherited: false,
type: CSS_TYPE_LONGHAND,
/* XXX requires position */
initial_values: [ "auto" ],
other_values: [ "0", "3", "-7000", "12000" ],
invalid_values: [ "3.0", "17.5" ]
--- a/layout/style/viewsource.css
+++ b/layout/style/viewsource.css
@@ -44,16 +44,17 @@
#viewsource {
font-family: -moz-fixed;
font-weight: normal;
color: black;
white-space: pre;
}
#viewsource.wrap {
white-space: pre-wrap;
+ word-wrap: break-word;
}
pre {
font: inherit;
color: inherit;
white-space: inherit;
margin: 0;
}
.start-tag {