Bug 1149009 - Suppress line break inside text frame if it is directly contained by ruby content box. r=dbaron

--HG--
extra : source : 27743ccd4b9be84847c7eb6590adcf96fb424999
This commit is contained in:
Xidorn Quan 2015-05-04 09:52:53 +12:00
parent ffec696346
commit 21b619291a
9 changed files with 52 additions and 11 deletions

View File

@ -1055,7 +1055,8 @@ nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
if (nsGkAtoms::textFrame == frameType) {
if (content != aBpd->mPrevContent) {
aBpd->mPrevContent = content;
if (!frame->StyleText()->NewlineIsSignificant(frame)) {
if (!frame->StyleText()->NewlineIsSignificant(
static_cast<nsTextFrame*>(frame))) {
content->AppendTextTo(aBpd->mBuffer);
} else {
/*

View File

@ -678,7 +678,7 @@ static bool IsSpaceCombiningSequenceTail(const nsTextFragment* aFrag, uint32_t a
// Check whether aPos is a space for CSS 'word-spacing' purposes
static bool
IsCSSWordSpacingSpace(const nsTextFragment* aFrag, uint32_t aPos,
nsIFrame* aFrame, const nsStyleText* aStyleText)
nsTextFrame* aFrame, const nsStyleText* aStyleText)
{
NS_ASSERTION(aPos < aFrag->GetLength(), "No text for IsSpace!");
@ -1942,7 +1942,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
textFlags |= GetSpacingFlags(WordSpacing(f));
nsTextFrameUtils::CompressionMode compression =
GetCSSWhitespaceToCompressionMode(f, textStyle);
if ((enabledJustification || f->StyleContext()->ShouldSuppressLineBreak()) &&
if ((enabledJustification || f->ShouldSuppressLineBreak()) &&
!textStyle->WhiteSpaceIsSignificant() && !isSVG) {
textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
}
@ -2816,9 +2816,9 @@ static int32_t FindChar(const nsTextFragment* frag,
return -1;
}
static bool IsChineseOrJapanese(nsIFrame* aFrame)
static bool IsChineseOrJapanese(nsTextFrame* aFrame)
{
if (aFrame->StyleContext()->ShouldSuppressLineBreak()) {
if (aFrame->ShouldSuppressLineBreak()) {
// Always treat ruby as CJ language so that those characters can
// be expanded properly even when surrounded by other language.
return true;
@ -8343,7 +8343,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
(GetStateBits() & TEXT_IS_IN_TOKEN_MATHML);
gfxBreakPriority breakPriority = aLineLayout.LastOptionalBreakPriority();
gfxTextRun::SuppressBreak suppressBreak = gfxTextRun::eNoSuppressBreak;
if (StyleContext()->ShouldSuppressLineBreak()) {
if (ShouldSuppressLineBreak()) {
suppressBreak = gfxTextRun::eSuppressAllBreaks;
} else if (!aLineLayout.LineIsBreakable()) {
suppressBreak = gfxTextRun::eSuppressInitialBreak;
@ -8552,7 +8552,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
bool emptyTextAtStartOfLine = atStartOfLine && length == 0;
if (!breakAfter && charsFit == length && !emptyTextAtStartOfLine &&
transformedOffset + transformedLength == mTextRun->GetLength() &&
!StyleContext()->ShouldSuppressLineBreak() &&
!ShouldSuppressLineBreak() &&
(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
@ -8614,7 +8614,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
if (!textStyle->WhiteSpaceIsSignificant() &&
(lineContainer->StyleText()->mTextAlign == NS_STYLE_TEXT_ALIGN_JUSTIFY ||
lineContainer->StyleText()->mTextAlignLast == NS_STYLE_TEXT_ALIGN_JUSTIFY ||
StyleContext()->ShouldSuppressLineBreak()) &&
ShouldSuppressLineBreak()) &&
!lineContainer->IsSVGText()) {
AddStateBits(TEXT_JUSTIFICATION_ENABLED);
provider.ComputeJustification(offset, charsFit);

View File

@ -15,6 +15,7 @@
#include "gfxTextRun.h"
#include "nsDisplayList.h"
#include "JustificationUtils.h"
#include "RubyUtils.h"
// Undo the windows.h damage
#if defined(XP_WIN) && defined(DrawText)
@ -122,6 +123,18 @@ public:
nsIFrame::eLineParticipant));
}
bool ShouldSuppressLineBreak() const
{
// If the parent frame of the text frame is ruby content box, it must
// suppress line break inside. This check is necessary, because when
// a whitespace is only contained by pseudo ruby frames, its style
// context won't have SuppressLineBreak bit set.
if (mozilla::RubyUtils::IsRubyContentBox(GetParent()->GetType())) {
return true;
}
return StyleContext()->ShouldSuppressLineBreak();
}
virtual void InvalidateFrame(uint32_t aDisplayItemKey = 0) override;
virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override;

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1149009 - Line break suppression on whitespaces wrapped but not contained in ruby boxes</title>
</head>
<body>
<span style="white-space: pre"><rb>a</rb><rb>
</rb><rb>b</rb></span>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1149009 - Line break suppression on whitespaces wrapped but not contained in ruby boxes</title>
</head>
<body>
<span style="white-space: pre"><rb>a</rb>
<rb>b</rb></span>
</body>
</html>

View File

@ -31,6 +31,7 @@ fuzzy-if(winWidget,255,792) == lang-specific-style-1.html lang-specific-style-1-
== line-break-suppression-1.html line-break-suppression-1-ref.html
== line-break-suppression-2.html line-break-suppression-2-ref.html
== line-break-suppression-3.html line-break-suppression-3-ref.html
== line-break-suppression-4.html line-break-suppression-4-ref.html
== line-height-1.html line-height-1-ref.html
== line-height-2.html line-height-2-ref.html
== line-height-3.html line-height-3-ref.html

View File

@ -157,6 +157,8 @@ public:
// as if nowrap is set, <br> is suppressed, and blocks are inlinized.
// This bit is propogated to all children of line partitipants. It is
// currently used by ruby to make its content frames unbreakable.
// NOTE: for nsTextFrame, use nsTextFrame::ShouldSuppressLineBreak()
// instead of this method.
bool ShouldSuppressLineBreak() const
{ return !!(mBits & NS_STYLE_SUPPRESS_LINEBREAK); }

View File

@ -30,6 +30,7 @@
#include "CounterStyleManager.h"
class nsIFrame;
class nsTextFrame;
class nsIURI;
class imgIContainer;
@ -1666,7 +1667,7 @@ struct nsStyleText {
// style struct is for. If the frame is for SVG text or inside ruby,
// the return value will be massaged to be something that makes sense
// for those cases.
inline bool NewlineIsSignificant(const nsIFrame* aContextFrame) const;
inline bool NewlineIsSignificant(const nsTextFrame* aContextFrame) const;
inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
};

View File

@ -14,6 +14,7 @@
#include "nsIFrame.h"
#include "nsStyleStruct.h"
#include "nsIContent.h" // for GetParent()
#include "nsTextFrame.h" // for nsTextFrame::ShouldSuppressLineBreak
inline void
nsStyleImage::SetSubImage(uint8_t aIndex, imgIContainer* aSubImage) const
@ -43,11 +44,11 @@ nsStyleText::GetTextShadow() const
}
bool
nsStyleText::NewlineIsSignificant(const nsIFrame* aContextFrame) const
nsStyleText::NewlineIsSignificant(const nsTextFrame* aContextFrame) const
{
NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
return NewlineIsSignificantStyle() &&
!aContextFrame->StyleContext()->ShouldSuppressLineBreak();
!aContextFrame->ShouldSuppressLineBreak();
}
bool