зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1083848 - Make InlineBackgroundData aware of vertical writing mode. r=dbaron
This commit is contained in:
Родитель
1c66529de8
Коммит
292ae32743
|
@ -85,9 +85,9 @@ struct InlineBackgroundData
|
|||
void Reset()
|
||||
{
|
||||
mBoundingBox.SetRect(0,0,0,0);
|
||||
mContinuationPoint = mLineContinuationPoint = mUnbrokenWidth = 0;
|
||||
mContinuationPoint = mLineContinuationPoint = mUnbrokenMeasure = 0;
|
||||
mFrame = mBlockFrame = nullptr;
|
||||
mLeftBorderData.Reset();
|
||||
mPIStartBorderData.Reset();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,25 +101,31 @@ struct InlineBackgroundData
|
|||
|
||||
SetFrame(aFrame);
|
||||
|
||||
nscoord x;
|
||||
nscoord pos; // an x coordinate if writing-mode is horizontal;
|
||||
// y coordinate if vertical
|
||||
if (mBidiEnabled) {
|
||||
x = mLineContinuationPoint;
|
||||
pos = mLineContinuationPoint;
|
||||
|
||||
// Scan continuations on the same line as aFrame and accumulate the widths
|
||||
// of frames that are to the left (if this is an LTR block) or right
|
||||
// (if it's RTL) of the current one.
|
||||
bool isRtlBlock = (mBlockFrame->StyleVisibility()->mDirection ==
|
||||
NS_STYLE_DIRECTION_RTL);
|
||||
nscoord curOffset = aFrame->GetOffsetTo(mBlockFrame).x;
|
||||
nscoord curOffset = mVertical ? aFrame->GetOffsetTo(mBlockFrame).y
|
||||
: aFrame->GetOffsetTo(mBlockFrame).x;
|
||||
|
||||
// If the continuation is fluid we know inlineFrame is not on the same line.
|
||||
// If it's not fluid, we need to test further to be sure.
|
||||
nsIFrame* inlineFrame = aFrame->GetPrevContinuation();
|
||||
while (inlineFrame && !inlineFrame->GetNextInFlow() &&
|
||||
AreOnSameLine(aFrame, inlineFrame)) {
|
||||
nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x;
|
||||
if(isRtlBlock == (frameXOffset >= curOffset)) {
|
||||
x += inlineFrame->GetSize().width;
|
||||
nscoord frameOffset = mVertical
|
||||
? inlineFrame->GetOffsetTo(mBlockFrame).y
|
||||
: inlineFrame->GetOffsetTo(mBlockFrame).x;
|
||||
if (isRtlBlock == (frameOffset >= curOffset)) {
|
||||
pos += mVertical
|
||||
? inlineFrame->GetSize().height
|
||||
: inlineFrame->GetSize().width;
|
||||
}
|
||||
inlineFrame = inlineFrame->GetPrevContinuation();
|
||||
}
|
||||
|
@ -127,59 +133,82 @@ struct InlineBackgroundData
|
|||
inlineFrame = aFrame->GetNextContinuation();
|
||||
while (inlineFrame && !inlineFrame->GetPrevInFlow() &&
|
||||
AreOnSameLine(aFrame, inlineFrame)) {
|
||||
nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x;
|
||||
if(isRtlBlock == (frameXOffset >= curOffset)) {
|
||||
x += inlineFrame->GetSize().width;
|
||||
nscoord frameOffset = mVertical
|
||||
? inlineFrame->GetOffsetTo(mBlockFrame).y
|
||||
: inlineFrame->GetOffsetTo(mBlockFrame).x;
|
||||
if (isRtlBlock == (frameOffset >= curOffset)) {
|
||||
pos += mVertical
|
||||
? inlineFrame->GetSize().height
|
||||
: inlineFrame->GetSize().width;
|
||||
}
|
||||
inlineFrame = inlineFrame->GetNextContinuation();
|
||||
}
|
||||
if (isRtlBlock) {
|
||||
// aFrame itself is also to the right of its left edge, so add its width.
|
||||
x += aFrame->GetSize().width;
|
||||
// x is now the distance from the left edge of aFrame to the right edge
|
||||
pos += mVertical ? aFrame->GetSize().height : aFrame->GetSize().width;
|
||||
// pos is now the distance from the left [top] edge of aFrame to the right [bottom] edge
|
||||
// of the unbroken content. Change it to indicate the distance from the
|
||||
// left edge of the unbroken content to the left edge of aFrame.
|
||||
x = mUnbrokenWidth - x;
|
||||
// left [top] edge of the unbroken content to the left [top] edge of aFrame.
|
||||
pos = mUnbrokenMeasure - pos;
|
||||
}
|
||||
} else {
|
||||
x = mContinuationPoint;
|
||||
pos = mContinuationPoint;
|
||||
}
|
||||
|
||||
// Assume background-origin: border and return a rect with offsets
|
||||
// relative to (0,0). If we have a different background-origin,
|
||||
// then our rect should be deflated appropriately by our caller.
|
||||
return nsRect(-x, 0, mUnbrokenWidth, mFrame->GetSize().height);
|
||||
return mVertical
|
||||
? nsRect(0, -pos, mFrame->GetSize().width, mUnbrokenMeasure)
|
||||
: nsRect(-pos, 0, mUnbrokenMeasure, mFrame->GetSize().height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a continuous rect for (an inline) aFrame relative to the
|
||||
* continuation that should draw the left-border. This is used when painting
|
||||
* continuation that should draw the left[top]-border. This is used when painting
|
||||
* borders and clipping backgrounds. This may NOT be the same continuous rect
|
||||
* as for drawing backgrounds; the continuation with the left-border might be
|
||||
* as for drawing backgrounds; the continuation with the left[top]-border might be
|
||||
* somewhere in the middle of that rect (e.g. BIDI), in those cases we need
|
||||
* the reverse background order starting at the left-border continuation.
|
||||
* the reverse background order starting at the left[top]-border continuation.
|
||||
*/
|
||||
nsRect GetBorderContinuousRect(nsIFrame* aFrame, nsRect aBorderArea)
|
||||
{
|
||||
// Calling GetContinuousRect(aFrame) here may lead to Reset/Init which
|
||||
// resets our mLeftBorderData so we save it ...
|
||||
LeftBorderData saved(mLeftBorderData);
|
||||
// resets our mPIStartBorderData so we save it ...
|
||||
PhysicalInlineStartBorderData saved(mPIStartBorderData);
|
||||
nsRect joinedBorderArea = GetContinuousRect(aFrame);
|
||||
if (!saved.mIsValid || saved.mFrame != mLeftBorderData.mFrame) {
|
||||
if (aFrame == mLeftBorderData.mFrame) {
|
||||
mLeftBorderData.SetX(joinedBorderArea.x);
|
||||
} else if (mLeftBorderData.mFrame) {
|
||||
mLeftBorderData.SetX(GetContinuousRect(mLeftBorderData.mFrame).x);
|
||||
if (!saved.mIsValid || saved.mFrame != mPIStartBorderData.mFrame) {
|
||||
if (aFrame == mPIStartBorderData.mFrame) {
|
||||
if (mVertical) {
|
||||
mPIStartBorderData.SetCoord(joinedBorderArea.y);
|
||||
} else {
|
||||
mPIStartBorderData.SetCoord(joinedBorderArea.x);
|
||||
}
|
||||
} else if (mPIStartBorderData.mFrame) {
|
||||
if (mVertical) {
|
||||
mPIStartBorderData.SetCoord(GetContinuousRect(mPIStartBorderData.mFrame).y);
|
||||
} else {
|
||||
mPIStartBorderData.SetCoord(GetContinuousRect(mPIStartBorderData.mFrame).x);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ... and restore it when possible.
|
||||
mLeftBorderData.mX = saved.mX;
|
||||
mPIStartBorderData.mCoord = saved.mCoord;
|
||||
}
|
||||
if (joinedBorderArea.x > mLeftBorderData.mX) {
|
||||
joinedBorderArea.x =
|
||||
-(mUnbrokenWidth + joinedBorderArea.x - aBorderArea.width);
|
||||
if (mVertical) {
|
||||
if (joinedBorderArea.y > mPIStartBorderData.mCoord) {
|
||||
joinedBorderArea.y =
|
||||
-(mUnbrokenMeasure + joinedBorderArea.y - aBorderArea.height);
|
||||
} else {
|
||||
joinedBorderArea.y -= mPIStartBorderData.mCoord;
|
||||
}
|
||||
} else {
|
||||
joinedBorderArea.x -= mLeftBorderData.mX;
|
||||
if (joinedBorderArea.x > mPIStartBorderData.mCoord) {
|
||||
joinedBorderArea.x =
|
||||
-(mUnbrokenMeasure + joinedBorderArea.x - aBorderArea.width);
|
||||
} else {
|
||||
joinedBorderArea.x -= mPIStartBorderData.mCoord;
|
||||
}
|
||||
}
|
||||
return joinedBorderArea;
|
||||
}
|
||||
|
@ -201,22 +230,27 @@ struct InlineBackgroundData
|
|||
}
|
||||
|
||||
protected:
|
||||
struct LeftBorderData {
|
||||
// This is a coordinate on the inline axis, but is not a true logical inline-
|
||||
// coord because it is always measured from left to right (if horizontal) or
|
||||
// from top to bottom (if vertical), ignoring any bidi RTL directionality.
|
||||
// We'll call this "physical inline start", or PIStart for short.
|
||||
struct PhysicalInlineStartBorderData {
|
||||
nsIFrame* mFrame; // the continuation that may have a left-border
|
||||
nscoord mX; // cached GetContinuousRect(mFrame).x
|
||||
bool mIsValid; // true if mX is valid
|
||||
nscoord mCoord; // cached GetContinuousRect(mFrame).x or .y
|
||||
bool mIsValid; // true if mCoord is valid
|
||||
void Reset() { mFrame = nullptr; mIsValid = false; }
|
||||
void SetX(nscoord aX) { mX = aX; mIsValid = true; }
|
||||
void SetCoord(nscoord aCoord) { mCoord = aCoord; mIsValid = true; }
|
||||
};
|
||||
|
||||
nsIFrame* mFrame;
|
||||
nsBlockFrame* mBlockFrame;
|
||||
nsRect mBoundingBox;
|
||||
nscoord mContinuationPoint;
|
||||
nscoord mUnbrokenWidth;
|
||||
nscoord mUnbrokenMeasure;
|
||||
nscoord mLineContinuationPoint;
|
||||
LeftBorderData mLeftBorderData;
|
||||
PhysicalInlineStartBorderData mPIStartBorderData;
|
||||
bool mBidiEnabled;
|
||||
bool mVertical;
|
||||
|
||||
void SetFrame(nsIFrame* aFrame)
|
||||
{
|
||||
|
@ -239,7 +273,8 @@ protected:
|
|||
|
||||
// Get our last frame's size and add its width to our continuation
|
||||
// point before we cache the new frame.
|
||||
mContinuationPoint += mFrame->GetSize().width;
|
||||
mContinuationPoint += mVertical ? mFrame->GetSize().height
|
||||
: mFrame->GetSize().width;
|
||||
|
||||
// If this a new line, update mLineContinuationPoint.
|
||||
if (mBidiEnabled &&
|
||||
|
@ -289,7 +324,7 @@ protected:
|
|||
|
||||
void Init(nsIFrame* aFrame)
|
||||
{
|
||||
mLeftBorderData.Reset();
|
||||
mPIStartBorderData.Reset();
|
||||
mBidiEnabled = aFrame->PresContext()->BidiEnabled();
|
||||
if (mBidiEnabled) {
|
||||
// Find the containing block frame
|
||||
|
@ -303,20 +338,23 @@ protected:
|
|||
NS_ASSERTION(mBlockFrame, "Cannot find containing block.");
|
||||
}
|
||||
|
||||
mVertical = aFrame->GetWritingMode().IsVertical();
|
||||
|
||||
// Start with the previous flow frame as our continuation point
|
||||
// is the total of the widths of the previous frames.
|
||||
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
||||
while (inlineFrame) {
|
||||
if (!mLeftBorderData.mFrame &&
|
||||
!inlineFrame->GetSkipSides().Left()) {
|
||||
mLeftBorderData.mFrame = inlineFrame;
|
||||
if (!mPIStartBorderData.mFrame &&
|
||||
!(mVertical ? inlineFrame->GetSkipSides().Top()
|
||||
: inlineFrame->GetSkipSides().Left())) {
|
||||
mPIStartBorderData.mFrame = inlineFrame;
|
||||
}
|
||||
nsRect rect = inlineFrame->GetRect();
|
||||
mContinuationPoint += rect.width;
|
||||
mContinuationPoint += mVertical ? rect.height : rect.width;
|
||||
if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) {
|
||||
mLineContinuationPoint += rect.width;
|
||||
mLineContinuationPoint += mVertical ? rect.height : rect.width;
|
||||
}
|
||||
mUnbrokenWidth += rect.width;
|
||||
mUnbrokenMeasure += mVertical ? rect.height : rect.width;
|
||||
mBoundingBox.UnionRect(mBoundingBox, rect);
|
||||
inlineFrame = GetPrevContinuation(inlineFrame);
|
||||
}
|
||||
|
@ -325,12 +363,13 @@ protected:
|
|||
// unbroken width.
|
||||
inlineFrame = aFrame;
|
||||
while (inlineFrame) {
|
||||
if (!mLeftBorderData.mFrame &&
|
||||
!inlineFrame->GetSkipSides().Left()) {
|
||||
mLeftBorderData.mFrame = inlineFrame;
|
||||
if (!mPIStartBorderData.mFrame &&
|
||||
!(mVertical ? inlineFrame->GetSkipSides().Top()
|
||||
: inlineFrame->GetSkipSides().Left())) {
|
||||
mPIStartBorderData.mFrame = inlineFrame;
|
||||
}
|
||||
nsRect rect = inlineFrame->GetRect();
|
||||
mUnbrokenWidth += rect.width;
|
||||
mUnbrokenMeasure += mVertical ? rect.height : rect.width;
|
||||
mBoundingBox.UnionRect(mBoundingBox, rect);
|
||||
inlineFrame = GetNextContinuation(inlineFrame);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче