зеркало из https://github.com/mozilla/gecko-dev.git
Bug 727125 - Lazily compute LineBaselineOffset when needed so it is present after a dynamic change of 'text-decoration'. r=dbaron
This fixes the positioning of underlines set on a block or its ancestor when drawn on children of a block that have a vertical-align != baseline. The lazy computation is done all at once for all children of a block to avoid O(N^2) searches for the line containing a frame.
This commit is contained in:
Родитель
f9d65507e2
Коммит
b85550ce86
|
@ -731,6 +731,16 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
printf("\n");
|
printf("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (mCurrentSpan == mRootSpan) {
|
||||||
|
pfd->mFrame->Properties().Remove(nsIFrame::LineBaselineOffset());
|
||||||
|
} else {
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool hasLineOffset;
|
||||||
|
pfd->mFrame->Properties().Get(nsIFrame::LineBaselineOffset(), &hasLineOffset);
|
||||||
|
NS_ASSERTION(!hasLineOffset, "LineBaselineOffset was set but was not expected");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
mTextJustificationNumSpaces = 0;
|
mTextJustificationNumSpaces = 0;
|
||||||
mTextJustificationNumLetters = 0;
|
mTextJustificationNumLetters = 0;
|
||||||
|
|
||||||
|
@ -1456,22 +1466,6 @@ nsLineLayout::VerticalAlignLine()
|
||||||
}
|
}
|
||||||
PlaceTopBottomFrames(psd, -mBStartEdge, lineBSize);
|
PlaceTopBottomFrames(psd, -mBStartEdge, lineBSize);
|
||||||
|
|
||||||
// If the frame being reflowed has text decorations, we simulate the
|
|
||||||
// propagation of those decorations to a line-level element by storing the
|
|
||||||
// offset in a frame property on any child frames that are aligned in the
|
|
||||||
// block direction somewhere other than the baseline. This property is then
|
|
||||||
// used by nsTextFrame::GetTextDecorations when the same conditions are met.
|
|
||||||
if (rootPFD.mFrame->StyleContext()->HasTextDecorationLines()) {
|
|
||||||
for (const PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
|
|
||||||
const nsIFrame *const f = pfd->mFrame;
|
|
||||||
if (f->VerticalAlignEnum() != NS_STYLE_VERTICAL_ALIGN_BASELINE) {
|
|
||||||
const nscoord offset = baselineBCoord - pfd->mBounds.BStart(lineWM);
|
|
||||||
f->Properties().Set(nsIFrame::LineBaselineOffset(),
|
|
||||||
NS_INT32_TO_PTR(offset));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in returned line-box and max-element-width data
|
// Fill in returned line-box and max-element-width data
|
||||||
mLineBox->SetBounds(lineWM,
|
mLineBox->SetBounds(lineWM,
|
||||||
psd->mIStart, mBStartEdge,
|
psd->mIStart, mBStartEdge,
|
||||||
|
|
|
@ -4620,6 +4620,40 @@ PaintSelectionBackground(gfxContext* aCtx, nsPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to get the LineBaselineOffset property of aChildFrame
|
||||||
|
// If not set, calculate this value for all child frames of aBlockFrame
|
||||||
|
static nscoord
|
||||||
|
LazyGetLineBaselineOffset(nsIFrame* aChildFrame, nsBlockFrame* aBlockFrame)
|
||||||
|
{
|
||||||
|
bool offsetFound;
|
||||||
|
nscoord offset = NS_PTR_TO_INT32(
|
||||||
|
aChildFrame->Properties().Get(nsIFrame::LineBaselineOffset(), &offsetFound)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!offsetFound) {
|
||||||
|
for (nsBlockFrame::line_iterator line = aBlockFrame->begin_lines(),
|
||||||
|
line_end = aBlockFrame->end_lines();
|
||||||
|
line != line_end; line++) {
|
||||||
|
if (line->IsInline()) {
|
||||||
|
int32_t n = line->GetChildCount();
|
||||||
|
nscoord lineBaseline = line->BStart() + line->GetLogicalAscent();
|
||||||
|
for (nsIFrame* lineFrame = line->mFirstChild;
|
||||||
|
n > 0; lineFrame = lineFrame->GetNextSibling(), --n) {
|
||||||
|
offset = lineBaseline - lineFrame->GetNormalPosition().y;
|
||||||
|
lineFrame->Properties().Set(nsIFrame::LineBaselineOffset(),
|
||||||
|
NS_INT32_TO_PTR(offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_PTR_TO_INT32(
|
||||||
|
aChildFrame->Properties().Get(nsIFrame::LineBaselineOffset(), &offsetFound)
|
||||||
|
);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTextFrame::GetTextDecorations(
|
nsTextFrame::GetTextDecorations(
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
|
@ -4663,7 +4697,8 @@ nsTextFrame::GetTextDecorations(
|
||||||
nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color);
|
nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool firstBlock = !nearestBlockFound && nsLayoutUtils::GetAsBlock(f);
|
nsBlockFrame* fBlock = nsLayoutUtils::GetAsBlock(f);
|
||||||
|
const bool firstBlock = !nearestBlockFound && fBlock;
|
||||||
|
|
||||||
// Not updating positions once we hit a parent block is equivalent to
|
// Not updating positions once we hit a parent block is equivalent to
|
||||||
// the CSS 2.1 spec that blocks should propagate decorations down to their
|
// the CSS 2.1 spec that blocks should propagate decorations down to their
|
||||||
|
@ -4674,13 +4709,15 @@ nsTextFrame::GetTextDecorations(
|
||||||
if (firstBlock) {
|
if (firstBlock) {
|
||||||
// At this point, fChild can't be null since TextFrames can't be blocks
|
// At this point, fChild can't be null since TextFrames can't be blocks
|
||||||
if (fChild->VerticalAlignEnum() != NS_STYLE_VERTICAL_ALIGN_BASELINE) {
|
if (fChild->VerticalAlignEnum() != NS_STYLE_VERTICAL_ALIGN_BASELINE) {
|
||||||
|
|
||||||
// Since offset is the offset in the child's coordinate space, we have
|
// Since offset is the offset in the child's coordinate space, we have
|
||||||
// to undo the accumulation to bring the transform out of the block's
|
// to undo the accumulation to bring the transform out of the block's
|
||||||
// coordinate space
|
// coordinate space
|
||||||
|
const nscoord lineBaselineOffset = LazyGetLineBaselineOffset(fChild,
|
||||||
|
fBlock);
|
||||||
|
|
||||||
baselineOffset =
|
baselineOffset =
|
||||||
frameTopOffset - fChild->GetNormalPosition().y
|
frameTopOffset - fChild->GetNormalPosition().y - lineBaselineOffset;
|
||||||
- NS_PTR_TO_INT32(
|
|
||||||
fChild->Properties().Get(nsIFrame::LineBaselineOffset()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!nearestBlockFound) {
|
else if (!nearestBlockFound) {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
.underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="underline">
|
||||||
|
<span class="align-bottom">This</span> line has a bottom vertical align span. <br />
|
||||||
|
<span class="align-top">This</span> line has a top vertical align span.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function addUnderline() {
|
||||||
|
var element = document.getElementById("dynamicUnderline");
|
||||||
|
element.style.textDecoration = "underline";
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
document.addEventListener('MozReftestInvalidate', addUnderline, false);
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="dynamicUnderline">
|
||||||
|
<span class="align-bottom">This</span> line has a bottom vertical align span. <br />
|
||||||
|
<span class="align-top">This</span> line has a top vertical align span.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,21 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
.underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="underline">
|
||||||
|
<span class="align-bottom">This line has only a bottom vertical align span.</span> <br />
|
||||||
|
<span class="align-top">This line has a top vertical align span.</span>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function addUnderline() {
|
||||||
|
var element = document.getElementById("dynamicUnderline");
|
||||||
|
element.style.textDecoration = "underline";
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
document.addEventListener('MozReftestInvalidate', addUnderline, false);
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="dynamicUnderline">
|
||||||
|
<span class="align-bottom">This line has only a bottom vertical align span.</span> <br />
|
||||||
|
<span class="align-top">This line has a top vertical align span.</span>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
.underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="underline">
|
||||||
|
<span class="align-bottom">This</span> line has a bottom vertical align span. <br />
|
||||||
|
<span class="align-top">This</span> line has a top vertical align span.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function addUnderline() {
|
||||||
|
var element = document.getElementById("dynamicUnderline");
|
||||||
|
element.style.textDecoration = "underline";
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
document.addEventListener('MozReftestInvalidate', addUnderline, false);
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="dynamicUnderline">
|
||||||
|
<span class="align-bottom">This</span> line has a bottom vertical align span. <br />
|
||||||
|
<span class="align-top">This</span> line has a top vertical align span.
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
.underline {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p class="underline">
|
||||||
|
<span class="align-bottom">This line has only a bottom vertical align span.</span> <br />
|
||||||
|
<span class="align-top">This line has a top vertical align span.</span>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-wait">
|
||||||
|
<head>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function addUnderline() {
|
||||||
|
var element = document.getElementById("dynamicUnderline");
|
||||||
|
element.style.textDecoration = "underline";
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
document.addEventListener('MozReftestInvalidate', addUnderline, false);
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.align-bottom {
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
.align-top {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p id="dynamicUnderline">
|
||||||
|
<span class="align-bottom">This line has only a bottom vertical align span.</span> <br />
|
||||||
|
<span class="align-top">This line has a top vertical align span.</span>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -4,6 +4,10 @@ skip-if(B2G) == complex-decoration-style-standards.html complex-decoration-style
|
||||||
== decoration-color-standards.html decoration-color-standards-ref.html
|
== decoration-color-standards.html decoration-color-standards-ref.html
|
||||||
== decoration-style-quirks.html decoration-style-quirks-ref.html
|
== decoration-style-quirks.html decoration-style-quirks-ref.html
|
||||||
== decoration-style-standards.html decoration-style-standards-ref.html
|
== decoration-style-standards.html decoration-style-standards-ref.html
|
||||||
|
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-quirks-1.html dynamic-underline-vertical-align-quirks-1-ref.html
|
||||||
|
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-standards-1.html dynamic-underline-vertical-align-standards-1-ref.html
|
||||||
|
fails == dynamic-underline-vertical-align-quirks-2.html dynamic-underline-vertical-align-quirks-2-ref.html
|
||||||
|
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-standards-2.html dynamic-underline-vertical-align-standards-2-ref.html
|
||||||
== line-through-style-block-solid-quirks.html line-through-style-block-quirks-ref.html
|
== line-through-style-block-solid-quirks.html line-through-style-block-quirks-ref.html
|
||||||
!= line-through-style-block-dotted-quirks.html line-through-style-block-quirks-ref.html
|
!= line-through-style-block-dotted-quirks.html line-through-style-block-quirks-ref.html
|
||||||
!= line-through-style-block-dashed-quirks.html line-through-style-block-quirks-ref.html
|
!= line-through-style-block-dashed-quirks.html line-through-style-block-quirks-ref.html
|
||||||
|
|
Загрузка…
Ссылка в новой задаче