зеркало из https://github.com/mozilla/gecko-dev.git
Fix text-decoration positioning in quirks mode and set overflow areas to match. (Bug 403524) r=dbaron
Change the quirks mode text-decoration code (soon to be used for all modes) to follow CSS 2.1's rules for positioning of decoration lines. Decorations are now drawn at a constant vertical position established by the element creating the decoration, and more than one of the same type (underline, overline, line-through) of decoration are supported on the same piece of text. This means that text-decorations can now significantly overflow a text frame, since the vertical-alignment of the element with text-decoration may be substantially different from the vertical alignment of the text. Set overflow areas for text frames with text decorations in nsLineLayout::RelativePositionFrames since it must happen *after* vertical alignment is done, and when relative positioning data are consistent (nsIFrame::GetRelativeOffset matches the offset that has been applied).
This commit is contained in:
Родитель
506fb4223e
Коммит
e915e08a19
|
@ -896,6 +896,8 @@ public:
|
|||
|
||||
NS_DECLARE_FRAME_PROPERTY(ScrollLayerCount, nsnull)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nsnull)
|
||||
|
||||
/**
|
||||
* Return the distance between the border edge of the frame and the
|
||||
* margin edge of the frame. Like GetRect(), returns the dimensions
|
||||
|
|
|
@ -1480,6 +1480,26 @@ nsLineLayout::VerticalAlignLine()
|
|||
}
|
||||
PlaceTopBottomFrames(psd, -mTopEdge, lineHeight);
|
||||
|
||||
// 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 vertically-aligned
|
||||
// somewhere other than the baseline. This property is then used by
|
||||
// nsTextFrame::GetTextDecorations when the same conditions are met.
|
||||
if (rootPFD.mFrame->GetStyleContext()->HasTextDecorationLines()) {
|
||||
for (const PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
|
||||
const nsIFrame *const f = pfd->mFrame;
|
||||
const nsStyleCoord& vAlign =
|
||||
f->GetStyleContext()->GetStyleTextReset()->mVerticalAlign;
|
||||
|
||||
if (vAlign.GetUnit() != eStyleUnit_Enumerated ||
|
||||
vAlign.GetIntValue() != NS_STYLE_VERTICAL_ALIGN_BASELINE) {
|
||||
const nscoord offset = baselineY - (pfd->mBounds.y);
|
||||
f->Properties().Set(nsIFrame::LineBaselineOffset(),
|
||||
NS_INT32_TO_PTR(offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in returned line-box and max-element-width data
|
||||
mLineBox->mBounds.x = psd->mLeftEdge;
|
||||
mLineBox->mBounds.y = mTopEdge;
|
||||
|
@ -2599,7 +2619,12 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflo
|
|||
} else {
|
||||
r = pfd->mOverflowAreas;
|
||||
if (pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||
if (pfd->GetFlag(PFD_RECOMPUTEOVERFLOW)) {
|
||||
// We need to recompute overflow areas in two cases:
|
||||
// (1) When PFD_RECOMPUTEOVERFLOW is set due to trimming
|
||||
// (2) When there are text decorations, since we can't recompute the
|
||||
// overflow area until Reflow and VerticalAlignLine have finished
|
||||
if (pfd->GetFlag(PFD_RECOMPUTEOVERFLOW) ||
|
||||
frame->GetStyleContext()->HasTextDecorationLines()) {
|
||||
nsTextFrame* f = static_cast<nsTextFrame*>(frame);
|
||||
r = f->RecomputeOverflow();
|
||||
}
|
||||
|
|
|
@ -439,10 +439,11 @@ protected:
|
|||
// return value, if that return value is not null. Calling
|
||||
// DestroySelectionDetails() on a null value is still OK, just not necessary.
|
||||
SelectionDetails* GetSelectionDetails();
|
||||
|
||||
void UnionTextDecorationOverflow(nsPresContext* aPresContext,
|
||||
PropertyProvider& aProvider,
|
||||
nsRect* aVisualOverflowRect);
|
||||
|
||||
void UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
PropertyProvider& aProvider,
|
||||
nsRect* aVisualOverflowRect,
|
||||
bool aIncludeTextDecorations);
|
||||
|
||||
void DrawText(gfxContext* aCtx,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
|
@ -465,40 +466,60 @@ protected:
|
|||
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
||||
nscoord aLeftSideOffset);
|
||||
|
||||
struct TextDecorations {
|
||||
PRUint8 mDecorations;
|
||||
PRUint8 mOverStyle;
|
||||
PRUint8 mUnderStyle;
|
||||
PRUint8 mStrikeStyle;
|
||||
nscolor mOverColor;
|
||||
nscolor mUnderColor;
|
||||
nscolor mStrikeColor;
|
||||
struct LineDecoration {
|
||||
nsIFrame* mFrame;
|
||||
|
||||
TextDecorations() :
|
||||
mDecorations(0), mOverStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID),
|
||||
mUnderStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID),
|
||||
mStrikeStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID),
|
||||
mOverColor(NS_RGB(0, 0, 0)), mUnderColor(NS_RGB(0, 0, 0)),
|
||||
mStrikeColor(NS_RGB(0, 0, 0))
|
||||
{ }
|
||||
// This is represents the offset from our baseline to mFrame's baseline;
|
||||
// positive offsets are *above* the baseline and negative offsets below
|
||||
nscoord mBaselineOffset;
|
||||
|
||||
PRBool HasDecorationlines() {
|
||||
return HasUnderline() || HasOverline() || HasStrikeout();
|
||||
}
|
||||
PRBool HasUnderline() {
|
||||
return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) &&
|
||||
mUnderStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE;
|
||||
}
|
||||
PRBool HasOverline() {
|
||||
return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) &&
|
||||
mOverStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE;
|
||||
}
|
||||
PRBool HasStrikeout() {
|
||||
return (mDecorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) &&
|
||||
mStrikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE;
|
||||
nscolor mColor;
|
||||
PRUint8 mStyle;
|
||||
|
||||
LineDecoration(nsIFrame *const aFrame,
|
||||
const nscoord aOff,
|
||||
const nscolor aColor,
|
||||
const PRUint8 aStyle)
|
||||
: mFrame(aFrame),
|
||||
mBaselineOffset(aOff),
|
||||
mColor(aColor),
|
||||
mStyle(aStyle)
|
||||
{}
|
||||
|
||||
LineDecoration(const LineDecoration& aOther)
|
||||
: mFrame(aOther.mFrame),
|
||||
mBaselineOffset(aOther.mBaselineOffset),
|
||||
mColor(aOther.mColor),
|
||||
mStyle(aOther.mStyle)
|
||||
{}
|
||||
|
||||
bool operator==(const LineDecoration& aOther) const {
|
||||
return mFrame == aOther.mFrame &&
|
||||
mStyle == aOther.mStyle &&
|
||||
mColor == aOther.mColor &&
|
||||
mBaselineOffset == aOther.mBaselineOffset;
|
||||
}
|
||||
};
|
||||
TextDecorations GetTextDecorations(nsPresContext* aPresContext);
|
||||
struct TextDecorations {
|
||||
nsAutoTArray<LineDecoration, 1> mOverlines, mUnderlines, mStrikes;
|
||||
|
||||
TextDecorations() { }
|
||||
|
||||
PRBool HasDecorationLines() const {
|
||||
return HasUnderline() || HasOverline() || HasStrikeout();
|
||||
}
|
||||
PRBool HasUnderline() const {
|
||||
return !mUnderlines.IsEmpty();
|
||||
}
|
||||
PRBool HasOverline() const {
|
||||
return !mOverlines.IsEmpty();
|
||||
}
|
||||
PRBool HasStrikeout() const {
|
||||
return !mStrikes.IsEmpty();
|
||||
}
|
||||
};
|
||||
void GetTextDecorations(nsPresContext* aPresContext,
|
||||
TextDecorations& aDecorations);
|
||||
|
||||
// Set non empty rect to aRect, it should be overflow rect or frame rect.
|
||||
// If the result rect is larger than the given rect, this returns PR_TRUE.
|
||||
|
|
|
@ -4260,11 +4260,10 @@ FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext,
|
|||
aCtx->Fill();
|
||||
}
|
||||
|
||||
nsTextFrame::TextDecorations
|
||||
nsTextFrame::GetTextDecorations(nsPresContext* aPresContext)
|
||||
void
|
||||
nsTextFrame::GetTextDecorations(nsPresContext* aPresContext,
|
||||
nsTextFrame::TextDecorations& aDecorations)
|
||||
{
|
||||
TextDecorations decorations;
|
||||
|
||||
// Quirks mode text decoration are rendered by children; see bug 1777
|
||||
// In non-quirks mode, nsHTMLContainer::Paint and nsBlockFrame::Paint
|
||||
// does the painting of text decorations.
|
||||
|
@ -4273,28 +4272,33 @@ nsTextFrame::GetTextDecorations(nsPresContext* aPresContext)
|
|||
// codepath. But for now this code is only used for quirks mode.
|
||||
const nsCompatibility compatMode = aPresContext->CompatibilityMode();
|
||||
if (compatMode != eCompatibility_NavQuirks)
|
||||
return decorations;
|
||||
return;
|
||||
|
||||
PRBool useOverride = PR_FALSE;
|
||||
nscolor overrideColor;
|
||||
|
||||
// A mask of all possible decorations.
|
||||
// FIXME: Per spec, we still need to draw all relevant decorations
|
||||
// from ancestors, not just the nearest one from each.
|
||||
PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
|
||||
// frameTopOffset represents the offset to f's top from our baseline in our
|
||||
// coordinate space
|
||||
// baselineOffset represents the offset from our baseline to f's baseline or
|
||||
// the nearest block's baseline, in our coordinate space, whichever is closest
|
||||
// during the particular iteration
|
||||
nscoord frameTopOffset = mAscent,
|
||||
baselineOffset = 0;
|
||||
|
||||
PRBool isChild; // ignored
|
||||
for (nsIFrame* f = this; decorMask && f;
|
||||
NS_SUCCEEDED(f->GetParentStyleContextFrame(aPresContext, &f, &isChild))
|
||||
|| (f = nsnull)) {
|
||||
nsStyleContext* context = f->GetStyleContext();
|
||||
bool nearestBlockFound = false;
|
||||
|
||||
for (nsIFrame* f = this, *fParent; f; f = fParent) {
|
||||
nsStyleContext *const context = f->GetStyleContext();
|
||||
if (!context->HasTextDecorationLines()) {
|
||||
break;
|
||||
}
|
||||
const nsStyleTextReset* styleText = context->GetStyleTextReset();
|
||||
if (!useOverride &&
|
||||
(NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL &
|
||||
styleText->mTextDecorationLine)) {
|
||||
|
||||
const nsStyleTextReset *const styleText = context->GetStyleTextReset();
|
||||
const PRUint8 textDecorations = styleText->mTextDecorationLine;
|
||||
|
||||
if (!useOverride &&
|
||||
(NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL & textDecorations))
|
||||
{
|
||||
// This handles the <a href="blah.html"><font color="green">La
|
||||
// la la</font></a> case. The link underline should be green.
|
||||
useOverride = PR_TRUE;
|
||||
|
@ -4302,38 +4306,51 @@ nsTextFrame::GetTextDecorations(nsPresContext* aPresContext)
|
|||
eCSSProperty_text_decoration_color);
|
||||
}
|
||||
|
||||
// FIXME: see above (remove this check)
|
||||
PRUint8 useDecorations = decorMask & styleText->mTextDecorationLine;
|
||||
if (useDecorations) {// a decoration defined here
|
||||
nscolor color = context->GetVisitedDependentColor(
|
||||
eCSSProperty_text_decoration_color);
|
||||
fParent = nsLayoutUtils::GetParentOrPlaceholderFor(
|
||||
aPresContext->FrameManager(), f);
|
||||
const bool firstBlock = !nearestBlockFound &&
|
||||
nsLayoutUtils::GetAsBlock(fParent);
|
||||
|
||||
// FIXME: We also need to record the thickness and position
|
||||
// metrics appropriate to this element (at least in standards
|
||||
// mode). This will require adjusting the visual overflow region
|
||||
// of this frame and maybe its ancestors. The positions should
|
||||
// probably be relative to the line's baseline (when text
|
||||
// decorations are specified on inlines we should look for their
|
||||
// containing line; otherwise use the element's font); when
|
||||
// drawing it should always be relative to the line baseline.
|
||||
// This way we move the decorations for relative positioning.
|
||||
if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & useDecorations) {
|
||||
decorations.mUnderColor = useOverride ? overrideColor : color;
|
||||
decorations.mUnderStyle = styleText->GetDecorationStyle();
|
||||
decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
|
||||
decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
|
||||
// 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
|
||||
// children (albeit the style should be preserved)
|
||||
// However, if we're vertically aligned within a block, then we need to
|
||||
// recover the right baseline from the line by querying the FrameProperty
|
||||
// that should be set (see nsLineLayout::VerticalAlignLine).
|
||||
if (firstBlock &&
|
||||
(styleText->mVerticalAlign.GetUnit() != eStyleUnit_Enumerated ||
|
||||
styleText->mVerticalAlign.GetIntValue() !=
|
||||
NS_STYLE_VERTICAL_ALIGN_BASELINE)) {
|
||||
baselineOffset = frameTopOffset -
|
||||
NS_PTR_TO_INT32(f->Properties().Get(nsIFrame::LineBaselineOffset()));
|
||||
}
|
||||
else if (!nearestBlockFound) {
|
||||
baselineOffset = frameTopOffset - f->GetBaseline();
|
||||
}
|
||||
|
||||
nearestBlockFound = nearestBlockFound || firstBlock;
|
||||
frameTopOffset += f->GetRect().Y() - f->GetRelativeOffset().y;
|
||||
|
||||
const PRUint8 style = styleText->GetDecorationStyle();
|
||||
// Accumulate only elements that have decorations with a genuine style
|
||||
if (textDecorations && style != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
|
||||
const nscolor color = useOverride ? overrideColor
|
||||
: context->GetVisitedDependentColor(eCSSProperty_text_decoration_color);
|
||||
|
||||
if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) {
|
||||
aDecorations.mUnderlines.AppendElement(
|
||||
nsTextFrame::LineDecoration(f, baselineOffset, color,
|
||||
style));
|
||||
}
|
||||
if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & useDecorations) {
|
||||
decorations.mOverColor = useOverride ? overrideColor : color;
|
||||
decorations.mOverStyle = styleText->GetDecorationStyle();
|
||||
decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
|
||||
decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
|
||||
if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) {
|
||||
aDecorations.mOverlines.AppendElement(
|
||||
nsTextFrame::LineDecoration(f, baselineOffset, color,
|
||||
style));
|
||||
}
|
||||
if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & useDecorations) {
|
||||
decorations.mStrikeColor = useOverride ? overrideColor : color;
|
||||
decorations.mStrikeStyle = styleText->GetDecorationStyle();
|
||||
decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
|
||||
decorations.mDecorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
|
||||
if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) {
|
||||
aDecorations.mStrikes.AppendElement(
|
||||
nsTextFrame::LineDecoration(f, baselineOffset, color,
|
||||
style));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4358,14 +4375,13 @@ nsTextFrame::GetTextDecorations(nsPresContext* aPresContext)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decorations;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::UnionTextDecorationOverflow(nsPresContext* aPresContext,
|
||||
PropertyProvider& aProvider,
|
||||
nsRect* aVisualOverflowRect)
|
||||
nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
PropertyProvider& aProvider,
|
||||
nsRect* aVisualOverflowRect,
|
||||
bool aIncludeTextDecorations)
|
||||
{
|
||||
// Text-shadow overflows
|
||||
nsRect shadowRect =
|
||||
|
@ -4381,10 +4397,75 @@ nsTextFrame::UnionTextDecorationOverflow(nsPresContext* aPresContext,
|
|||
nsRect fontRect(0, mAscent - fontAscent, GetSize().width, fontHeight);
|
||||
aVisualOverflowRect->UnionRect(*aVisualOverflowRect, fontRect);
|
||||
}
|
||||
if (aIncludeTextDecorations) {
|
||||
// Since CSS 2.1 requires that text-decoration defined on ancestors maintain
|
||||
// style and position, they can be drawn at virtually any y-offset, so
|
||||
// maxima and minima are required to reliably generate the rectangle for
|
||||
// them
|
||||
TextDecorations textDecs;
|
||||
GetTextDecorations(aPresContext, textDecs);
|
||||
if (textDecs.HasDecorationLines()) {
|
||||
const nscoord width = GetSize().width;
|
||||
const gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(),
|
||||
gfxWidth = width / appUnitsPerDevUnit,
|
||||
ascent = gfxFloat(mAscent) / appUnitsPerDevUnit;
|
||||
nscoord top(nscoord_MAX), bottom(nscoord_MIN);
|
||||
// Below we loop through all text decorations and compute the rectangle
|
||||
// containing all of them, in this frame's coordinate space
|
||||
for (PRUint32 i = 0; i < textDecs.mUnderlines.Length(); ++i) {
|
||||
const LineDecoration& dec = textDecs.mUnderlines[i];
|
||||
|
||||
const gfxFont::Metrics metrics =
|
||||
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame));
|
||||
|
||||
const nsRect decorationRect =
|
||||
nsCSSRendering::GetTextDecorationRect(aPresContext,
|
||||
gfxSize(gfxWidth, metrics.underlineSize),
|
||||
ascent, metrics.underlineOffset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, dec.mStyle) +
|
||||
nsPoint(0, -dec.mBaselineOffset);
|
||||
|
||||
top = NS_MIN(decorationRect.y, top);
|
||||
bottom = NS_MAX(decorationRect.YMost(), bottom);
|
||||
}
|
||||
for (PRUint32 i = 0; i < textDecs.mOverlines.Length(); ++i) {
|
||||
const LineDecoration& dec = textDecs.mOverlines[i];
|
||||
|
||||
const gfxFont::Metrics metrics =
|
||||
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame));
|
||||
|
||||
const nsRect decorationRect =
|
||||
nsCSSRendering::GetTextDecorationRect(aPresContext,
|
||||
gfxSize(gfxWidth, metrics.underlineSize),
|
||||
ascent, metrics.maxAscent,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle) +
|
||||
nsPoint(0, -dec.mBaselineOffset);
|
||||
|
||||
top = NS_MIN(decorationRect.y, top);
|
||||
bottom = NS_MAX(decorationRect.YMost(), bottom);
|
||||
}
|
||||
for (PRUint32 i = 0; i < textDecs.mStrikes.Length(); ++i) {
|
||||
const LineDecoration& dec = textDecs.mStrikes[i];
|
||||
|
||||
const gfxFont::Metrics metrics =
|
||||
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame));
|
||||
|
||||
const nsRect decorationRect =
|
||||
nsCSSRendering::GetTextDecorationRect(aPresContext,
|
||||
gfxSize(gfxWidth, metrics.strikeoutSize),
|
||||
ascent, metrics.strikeoutOffset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, dec.mStyle) +
|
||||
nsPoint(0, -dec.mBaselineOffset);
|
||||
top = NS_MIN(decorationRect.y, top);
|
||||
bottom = NS_MAX(decorationRect.YMost(), bottom);
|
||||
}
|
||||
|
||||
aVisualOverflowRect->UnionRect(*aVisualOverflowRect,
|
||||
nsRect(0, top, width, bottom - top));
|
||||
}
|
||||
}
|
||||
// When this frame is not selected, the text-decoration area must be in
|
||||
// frame bounds.
|
||||
nsRect decorationRect;
|
||||
if (!(GetStateBits() & NS_FRAME_SELECTED_CONTENT) ||
|
||||
!CombineSelectionUnderlineRect(aPresContext, *aVisualOverflowRect))
|
||||
return;
|
||||
|
@ -4401,52 +4482,67 @@ nsTextFrame::PaintTextDecorations(
|
|||
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
||||
const nscolor* aOverrideColor)
|
||||
{
|
||||
TextDecorations decorations =
|
||||
GetTextDecorations(aTextPaintStyle.PresContext());
|
||||
if (!decorations.HasDecorationlines())
|
||||
TextDecorations decorations;
|
||||
GetTextDecorations(aTextPaintStyle.PresContext(), decorations);
|
||||
|
||||
if (!decorations.HasDecorationLines())
|
||||
return;
|
||||
|
||||
// Hide text decorations if we're currently hiding @font-face fallback text
|
||||
if (aProvider.GetFontGroup()->ShouldSkipDrawing())
|
||||
return;
|
||||
|
||||
gfxFont* firstFont = aProvider.GetFontGroup()->GetFontAt(0);
|
||||
if (!firstFont)
|
||||
return; // OOM
|
||||
const gfxFont::Metrics& fontMetrics = firstFont->GetMetrics();
|
||||
gfxFloat app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
|
||||
const gfxFloat app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
|
||||
|
||||
// XXX aFramePt is in AppUnits, shouldn't it be nsFloatPoint?
|
||||
nscoord x = NSToCoordRound(aFramePt.x);
|
||||
nscoord width = GetRect().width;
|
||||
aClipEdges.Intersect(&x, &width);
|
||||
gfxPoint pt(x / app, (aTextBaselinePt.y - mAscent) / app);
|
||||
gfxPoint pt(x / app, 0);
|
||||
gfxSize size(width / app, 0);
|
||||
gfxFloat ascent = gfxFloat(mAscent) / app;
|
||||
const gfxFloat ascent = gfxFloat(mAscent) / app;
|
||||
const nscoord baseline = aTextBaselinePt.y - mAscent;
|
||||
|
||||
nscolor lineColor;
|
||||
if (decorations.HasOverline()) {
|
||||
lineColor = aOverrideColor ? *aOverrideColor : decorations.mOverColor;
|
||||
size.height = fontMetrics.underlineSize;
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aCtx, lineColor, pt, size, ascent, fontMetrics.maxAscent,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorations.mOverStyle);
|
||||
for (PRUint32 i = decorations.mUnderlines.Length(); i-- > 0; ) {
|
||||
const LineDecoration& dec = decorations.mUnderlines[i];
|
||||
gfxFontGroup* fontGroup = GetFontGroupForFrame(dec.mFrame);
|
||||
const gfxFont::Metrics metrics = GetFirstFontMetrics(fontGroup);
|
||||
|
||||
size.height = metrics.underlineSize;
|
||||
pt.y = (baseline - dec.mBaselineOffset) / app;
|
||||
|
||||
lineColor = aOverrideColor ? *aOverrideColor : dec.mColor;
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, lineColor, pt, size, ascent,
|
||||
fontGroup->GetUnderlineOffset(), NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
|
||||
dec.mStyle);
|
||||
}
|
||||
if (decorations.HasUnderline()) {
|
||||
lineColor = aOverrideColor ? *aOverrideColor : decorations.mUnderColor;
|
||||
size.height = fontMetrics.underlineSize;
|
||||
gfxFloat offset = aProvider.GetFontGroup()->GetUnderlineOffset();
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aCtx, lineColor, pt, size, ascent, offset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorations.mUnderStyle);
|
||||
for (PRUint32 i = decorations.mOverlines.Length(); i-- > 0; ) {
|
||||
const LineDecoration& dec = decorations.mOverlines[i];
|
||||
|
||||
const gfxFont::Metrics metrics =
|
||||
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame));
|
||||
|
||||
size.height = metrics.underlineSize;
|
||||
pt.y = (baseline - dec.mBaselineOffset) / app;
|
||||
|
||||
lineColor = aOverrideColor ? *aOverrideColor : dec.mColor;
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, lineColor, pt, size, ascent,
|
||||
metrics.maxAscent, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle);
|
||||
}
|
||||
if (decorations.HasStrikeout()) {
|
||||
lineColor = aOverrideColor ? *aOverrideColor : decorations.mStrikeColor;
|
||||
size.height = fontMetrics.strikeoutSize;
|
||||
gfxFloat offset = fontMetrics.strikeoutOffset;
|
||||
nsCSSRendering::PaintDecorationLine(
|
||||
aCtx, lineColor, pt, size, ascent, offset,
|
||||
NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorations.mStrikeStyle);
|
||||
for (PRUint32 i = decorations.mStrikes.Length(); i-- > 0; ) {
|
||||
const LineDecoration& dec = decorations.mStrikes[i];
|
||||
|
||||
const gfxFont::Metrics metrics =
|
||||
GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame));
|
||||
|
||||
size.height = metrics.strikeoutSize;
|
||||
pt.y = (baseline - dec.mBaselineOffset) / app;
|
||||
|
||||
lineColor = aOverrideColor ? *aOverrideColor : dec.mColor;
|
||||
nsCSSRendering::PaintDecorationLine(aCtx, lineColor, pt, size, ascent,
|
||||
metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
|
||||
dec.mStyle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7094,7 +7190,11 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
|||
aMetrics.SetOverflowAreasToDesiredBounds();
|
||||
aMetrics.VisualOverflow().UnionRect(aMetrics.VisualOverflow(), boundingBox);
|
||||
|
||||
UnionTextDecorationOverflow(presContext, provider, &aMetrics.VisualOverflow());
|
||||
// When we have text decorations, we don't need to compute their overflow now
|
||||
// because we're guaranteed to do it later
|
||||
// (see nsLineLayout::RelativePositionFrames)
|
||||
UnionAdditionalOverflow(presContext, provider, &aMetrics.VisualOverflow(),
|
||||
false);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// Clean up, update state
|
||||
|
@ -7348,15 +7448,11 @@ nsTextFrame::RecomputeOverflow()
|
|||
ComputeTransformedLength(provider),
|
||||
gfxFont::LOOSE_INK_EXTENTS, nsnull,
|
||||
&provider);
|
||||
|
||||
nsRect &vis = result.VisualOverflow();
|
||||
vis.UnionRect(vis, RoundOut(textMetrics.mBoundingBox) + nsPoint(0, mAscent));
|
||||
|
||||
UnionTextDecorationOverflow(PresContext(), provider, &vis);
|
||||
|
||||
UnionAdditionalOverflow(PresContext(), provider, &vis, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PRUnichar TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun,
|
||||
PRUint32 aSkippedOffset, PRUnichar aChar)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.high {vertical-align: 5em;}
|
||||
.invisible {color: transparent;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<span style="text-decoration: underline;">
|
||||
underline<span class="invisible">continued<span class="invisible">continued</span></span></span>
|
||||
<span class="invisible high">offset<span class="invisible high">offset</span></span>
|
||||
</div>
|
||||
<span style="text-decoration: underline;">also underlined</span>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,14 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.high {vertical-align: 5em;}
|
||||
.invisible {color: transparent;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="text-decoration: underline;">
|
||||
underline<span class="invisible high">continued<span class="invisible high">continued</span></span><br>
|
||||
also underlined
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.sup {vertical-align: super;}
|
||||
.transparent {color: transparent;}
|
||||
.alllines {text-decoration:line-through overline underline; color: purple;}
|
||||
.highRel {position: relative; top: -4em;}
|
||||
.lowRel {position: relative; top: 4em;}
|
||||
.lowVert {vertical-align: -4em;}
|
||||
.highVert {vertical-align: 4em;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<span style="text-decoration: underline">Underlined <span class="transparent">still underlined</span></span>
|
||||
<span style="text-decoration: underline">Underlined <span> </span></span>
|
||||
<span class="sup transparent">Offset</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="alllines">
|
||||
Before<span class="transparent">highlow</span>After</span>
|
||||
</span>
|
||||
<span class="highVert transparent">Offset</span><span class="lowVert transparent">text</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="alllines">Before</span><span class="highRel alllines">high</span><span class="lowRel alllines">low</span><span class="alllines">After</span>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,29 @@
|
|||
<html>
|
||||
<head>
|
||||
<style>
|
||||
.sup {vertical-align: super;}
|
||||
.transparent {color: transparent;}
|
||||
.alllines {text-decoration:line-through overline underline; color: purple;}
|
||||
.highRel {position: relative; top: -4em;}
|
||||
.lowRel {position: relative; top: 4em;}
|
||||
.lowVert {vertical-align: -4em;}
|
||||
.highVert {vertical-align: 4em;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
<span style="text-decoration: underline">Underlined <span class="sup transparent">still underlined</span></span>
|
||||
<span style="text-decoration: underline">Underlined <span class="sup"> </span></span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="alllines">
|
||||
Before<span class="highVert transparent">high</span><span class="lowVert transparent">low</span>After
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="alllines">
|
||||
Before<span class="highRel">high</span><span class="lowRel">low</span>After</span>
|
||||
</span>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
|
@ -20,11 +20,13 @@
|
|||
<span style="text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: dotted;">
|
||||
Here has dotted decoration lines,
|
||||
</span><span style="font-size: 2em;
|
||||
text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: wavy;">
|
||||
</span><span style="text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: dotted">
|
||||
<span style="font-size: 2em;
|
||||
text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: wavy;">
|
||||
here has wavy decoration
|
||||
lines</span><span style="text-decoration: underline line-through overline;
|
||||
lines</span></span><span style="text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: dotted;">,
|
||||
and here has dotted decoration lines.</span>
|
||||
</p>
|
||||
|
@ -32,13 +34,11 @@
|
|||
<span style="text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: double;">
|
||||
Here has double decoration lines,
|
||||
</span><span style="font-size: 2em;
|
||||
text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: double;">
|
||||
<span style="font-size: 2em;">
|
||||
here is specified as dashed decoration lines but should be
|
||||
ignored</span><span style="text-decoration: underline line-through overline;
|
||||
-moz-text-decoration-style: double;">,
|
||||
and here has double decoration lines.</span>
|
||||
and here has double decoration lines.</span></span>
|
||||
</p>
|
||||
<p>
|
||||
Here is specified the decoration style as -moz-none.
|
||||
|
|
|
@ -89,3 +89,5 @@ fails == text-decoration-zorder-1-quirks.html text-decoration-zorder-1-ref.html
|
|||
== text-decoration-propagation-1-quirks.html text-decoration-propagation-1-quirks-ref.html
|
||||
fails == text-decoration-propagation-1-standards.html text-decoration-propagation-1-standards-ref.html
|
||||
== 641444-1.html 641444-1-ref.html
|
||||
== decoration-css21.html decoration-css21-ref.html # bug 403524
|
||||
== decoration-css21-block.html decoration-css21-block-ref.html # bug 403524
|
||||
|
|
|
@ -134,6 +134,7 @@
|
|||
filter: inherit;
|
||||
mask: inherit;
|
||||
opacity: inherit;
|
||||
text-decoration: inherit;
|
||||
-moz-box-ordinal-group: inherit !important;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче