From 33b8312a5c69ca51960c6790c713cdf44f528e90 Mon Sep 17 00:00:00 2001 From: "masayuki@d-toybox.com" Date: Mon, 6 Aug 2007 01:15:00 -0700 Subject: [PATCH] Bug 365336 text-decoration width should be rounded to the device pixels r+sr=roc --- layout/base/nsCSSRendering.cpp | 125 +++++++++++++++++++++++ layout/base/nsCSSRendering.h | 40 ++++++++ layout/generic/nsBlockFrame.cpp | 20 +++- layout/generic/nsBlockFrame.h | 3 +- layout/generic/nsHTMLContainerFrame.cpp | 26 +++-- layout/generic/nsHTMLContainerFrame.h | 9 +- layout/generic/nsTextFrameThebes.cpp | 105 +++++++++++-------- layout/mathml/base/src/Makefile.in | 1 + layout/tables/Makefile.in | 1 + layout/xul/base/src/grid/Makefile.in | 1 + layout/xul/base/src/nsTextBoxFrame.cpp | 39 +++++-- layout/xul/base/src/tree/src/Makefile.in | 1 + 12 files changed, 305 insertions(+), 66 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 090ff1ad0a1..d36e2f997c6 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -4355,3 +4355,128 @@ nsCSSRendering::DrawTableBorderSegment(nsIRenderingContext& aContext, // End table border-collapsing section +void +nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext, + const nscolor aColor, + const gfxPoint& aPt, + const gfxSize& aLineSize, + const gfxFloat aAscent, + const gfxFloat aOffset, + const gfxFloat aPreferredHeight, + const PRUint8 aDecoration, + const PRUint8 aStyle, + const PRBool aIsRTL) +{ + if (aLineSize.width <= 0 || aLineSize.height <= 0 || + aStyle == NS_STYLE_BORDER_STYLE_NONE) + return; + + PRBool contextIsSaved = PR_FALSE; + gfxFloat totalHeight = aLineSize.height; + switch (aStyle) { + case NS_STYLE_BORDER_STYLE_SOLID: + break; + case NS_STYLE_BORDER_STYLE_DASHED: { + aGfxContext->Save(); + contextIsSaved = PR_TRUE; + gfxFloat dashWidth = aLineSize.height * DOT_LENGTH * DASH_LENGTH; + gfxFloat dash[2] = { dashWidth, dashWidth }; + aGfxContext->SetLineCap(gfxContext::LINE_CAP_BUTT); + aGfxContext->SetDash(dash, 2, 0.0); + break; + } + case NS_STYLE_BORDER_STYLE_DOTTED: { + aGfxContext->Save(); + contextIsSaved = PR_TRUE; + gfxFloat dashWidth = aLineSize.height * DOT_LENGTH; + gfxFloat dash[2]; + if (aLineSize.height > 2.0) { + dash[0] = 0.0; + dash[1] = dashWidth * 2.0; + aGfxContext->SetLineCap(gfxContext::LINE_CAP_ROUND); + } else { + dash[0] = dashWidth; + dash[1] = dashWidth; + } + aGfxContext->SetDash(dash, 2, 0.0); + break; + } + case NS_STYLE_BORDER_STYLE_DOUBLE: + totalHeight *= 3.0; + break; + default: + NS_ERROR("Invalid style value!"); + return; + } + + gfxFloat offset = aOffset; + switch (aDecoration) { + case NS_STYLE_TEXT_DECORATION_UNDERLINE: + break; + case NS_STYLE_TEXT_DECORATION_OVERLINE: + // The offset includes the preferred size, we should remove it + offset += aPreferredHeight; + // the bottom of the decoration line should be aligned to the top of the + // text. + offset -= totalHeight; + break; + case NS_STYLE_TEXT_DECORATION_LINE_THROUGH: { + // The offset includes the preferred size, we should remove it + offset += aPreferredHeight; + // the middle of the decoration line should be aligned to the middle of + // the original strike out offset. + offset -= PR_MAX(aPreferredHeight, (totalHeight / 2.0)); + break; + } + default: + NS_ERROR("Invalid decoration value!"); + if (contextIsSaved) + aGfxContext->Restore(); + return; + } + + // round to device pixels for suppressing the AA. + gfxFloat x = NS_round(aPt.x); + gfxFloat y = NS_round(aPt.y + aAscent - offset); + gfxFloat width = NS_round(aLineSize.width); + gfxFloat height = NS_round(aLineSize.height); + // The y position should be set to the middle of the line. + y += height / 2; + + aGfxContext->SetColor(gfxRGBA(aColor)); + aGfxContext->SetLineWidth(height); + switch (aStyle) { + case NS_STYLE_BORDER_STYLE_SOLID: + aGfxContext->NewPath(); + aGfxContext->MoveTo(gfxPoint(x, y)); + aGfxContext->LineTo(gfxPoint(x + width, y)); + aGfxContext->Stroke(); + break; + case NS_STYLE_BORDER_STYLE_DOUBLE: + aGfxContext->NewPath(); + aGfxContext->MoveTo(gfxPoint(x, y)); + aGfxContext->LineTo(gfxPoint(x + width, y)); + aGfxContext->MoveTo(gfxPoint(x, y + height * 2.0)); + aGfxContext->LineTo(gfxPoint(x + width, y + height * 2.0)); + aGfxContext->Stroke(); + break; + case NS_STYLE_BORDER_STYLE_DOTTED: + case NS_STYLE_BORDER_STYLE_DASHED: + aGfxContext->NewPath(); + if (aIsRTL) { + aGfxContext->MoveTo(gfxPoint(x + width, y)); + aGfxContext->LineTo(gfxPoint(x, y)); + } else { + aGfxContext->MoveTo(gfxPoint(x, y)); + aGfxContext->LineTo(gfxPoint(x + width, y)); + } + aGfxContext->Stroke(); + aGfxContext->Restore(); + contextIsSaved = PR_FALSE; + break; + default: + NS_ERROR("Invalid style value!"); + break; + } + NS_ASSERTION(!contextIsSaved, "The gfxContext has been saved, but not restored!"); +} diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index 336b620fdbe..59f61d67a4f 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -41,6 +41,7 @@ #define nsCSSRendering_h___ #include "nsIRenderingContext.h" +#include "gfxContext.h" struct nsPoint; class nsStyleContext; class nsPresContext; @@ -198,6 +199,45 @@ public: */ static nscolor TransformColor(nscolor aMapColor,PRBool aNoBackGround); + /** + * Function for painting the decoration lines for the text. + * NOTE: aPt, aLineSize, aAscent, aOffset and aReferredHeight are non-rounded + * device pixels, not app units. + * input: + * @param aGfxContext + * @param aColor the color of the decoration line + * @param aPt the top/left edge of the text + * @param aLineSize the width and the height of the decoration + * line + * @param aAscent the ascent of the text + * @param aOffset the offset of the decoration line from + * the baseline of the text (if the value is + * positive, the line is lifted up) + * @param aPreferredHeight the preferred size of the decoration line by + * the font of the text + * @param aDecoration which line will be painted. The value can be + * NS_STYLE_TEXT_DECORATION_UNDERLINE or + * NS_STYLE_TEXT_DECORATION_OVERLINE or + * NS_STYLE_TEXT_DECORATION_LINE_THROUGH. + * @param aStyle the style of the decoration line. The value + * can be NS_STYLE_BORDER_STYLE_SOLID or + * NS_STYLE_BORDER_STYLE_DOTTED or + * NS_STYLE_BORDER_STYLE_DASHED or + * NS_STYLE_BORDER_STYLE_DOUBLE or + * NS_STYLE_BORDER_STYLE_NONE. + * @param aIsRTL when the text is RTL, it is true. + */ + static void PaintDecorationLine(gfxContext* aGfxContext, + const nscolor aColor, + const gfxPoint& aPt, + const gfxSize& aLineSize, + const gfxFloat aAscent, + const gfxFloat aOffset, + const gfxFloat aPreferredSize, + const PRUint8 aDecoration, + const PRUint8 aStyle, + const PRBool aIsRTL); + protected: static void PaintBackgroundColor(nsPresContext* aPresContext, diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index fcff4c32698..a7c52880349 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -88,6 +88,7 @@ #include "nsDisplayList.h" #include "nsContentErrors.h" #include "nsCSSAnonBoxes.h" +#include "nsCSSRendering.h" #ifdef IBMBIDI #include "nsBidiPresUtils.h" @@ -5663,9 +5664,9 @@ nsBlockFrame::PaintTextDecorationLine(nsIRenderingContext& aRenderingContext, nscolor aColor, nscoord aOffset, nscoord aAscent, - nscoord aSize) + nscoord aSize, + const PRUint8 aDecoration) { - aRenderingContext.SetColor(aColor); NS_ASSERTION(!aLine->IsBlock(), "Why did we ask for decorations on a block?"); nscoord start = aLine->mBounds.x; @@ -5698,9 +5699,18 @@ nsBlockFrame::PaintTextDecorationLine(nsIRenderingContext& aRenderingContext, // Only paint if we have a positive width if (width > 0) { - aRenderingContext.FillRect(start + aPt.x, - aLine->mBounds.y + aLine->GetAscent() - aOffset + aPt.y, - width, aSize); + const nsStyleVisibility* visibility = GetStyleVisibility(); + PRBool isRTL = visibility->mDirection == NS_STYLE_DIRECTION_RTL; + nsRefPtr ctx = (gfxContext*) + aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); + gfxFloat a2p = 1.0 / PresContext()->AppUnitsPerDevPixel(); + gfxPoint pt((start + aPt.x) * a2p, (aLine->mBounds.y + aPt.y) * a2p); + gfxSize size(width * a2p, aSize * a2p); + nsCSSRendering::PaintDecorationLine(ctx, aColor, pt, size, + aLine->GetAscent() * a2p, aOffset * a2p, + aSize * a2p, aDecoration, + NS_STYLE_BORDER_STYLE_SOLID, + isRTL); } } diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 50af89bce24..b50eefdbd38 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -316,7 +316,8 @@ protected: nscolor aColor, nscoord aOffset, nscoord aAscent, - nscoord aSize); + nscoord aSize, + const PRUint8 aDecoration); void TryAllLines(nsLineList::iterator* aIterator, nsLineList::iterator* aEndIterator, diff --git a/layout/generic/nsHTMLContainerFrame.cpp b/layout/generic/nsHTMLContainerFrame.cpp index 7529f3c8d28..e8512346d8c 100644 --- a/layout/generic/nsHTMLContainerFrame.cpp +++ b/layout/generic/nsHTMLContainerFrame.cpp @@ -67,6 +67,7 @@ #include "nsBlockFrame.h" #include "nsLineBox.h" #include "nsDisplayList.h" +#include "nsCSSRendering.h" class nsDisplayTextDecoration : public nsDisplayItem { public: @@ -117,13 +118,16 @@ nsDisplayTextDecoration::Paint(nsDisplayListBuilder* aBuilder, if (mDecoration != NS_STYLE_TEXT_DECORATION_LINE_THROUGH) { fm->GetUnderline(offset, size); if (mDecoration == NS_STYLE_TEXT_DECORATION_UNDERLINE) { - f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, offset, ascent, size); + f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, + offset, ascent, size, mDecoration); } else if (mDecoration == NS_STYLE_TEXT_DECORATION_OVERLINE) { - f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, ascent, ascent, size); + f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, + ascent, ascent, size, mDecoration); } } else { fm->GetStrikeout(offset, size); - f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, offset, ascent, size); + f->PaintTextDecorationLine(*aCtx, pt, mLine, mColor, + offset, ascent, size, mDecoration); } } @@ -203,7 +207,8 @@ nsHTMLContainerFrame::PaintTextDecorationLine( nscolor aColor, nscoord aOffset, nscoord aAscent, - nscoord aSize) + nscoord aSize, + const PRUint8 aDecoration) { NS_ASSERTION(!aLine, "Should not have passed a linebox to a non-block frame"); nsMargin bp = GetUsedBorderAndPadding(); @@ -213,10 +218,17 @@ nsHTMLContainerFrame::PaintTextDecorationLine( bp.side(side) = 0; } } - aRenderingContext.SetColor(aColor); + const nsStyleVisibility* visibility = GetStyleVisibility(); + PRBool isRTL = visibility->mDirection == NS_STYLE_DIRECTION_RTL; nscoord innerWidth = mRect.width - bp.left - bp.right; - aRenderingContext.FillRect(bp.left + aPt.x, - bp.top + aAscent - aOffset + aPt.y, innerWidth, aSize); + nsRefPtr ctx = (gfxContext*) + aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); + gfxFloat a2p = 1.0 / PresContext()->AppUnitsPerDevPixel(); + gfxPoint pt((bp.left + aPt.x) * a2p, (bp.top + aPt.y) * a2p); + gfxSize size(innerWidth * a2p, aSize * a2p); + nsCSSRendering::PaintDecorationLine(ctx, aColor, pt, size, aAscent * a2p, + aOffset * a2p, aSize * a2p, aDecoration, + NS_STYLE_BORDER_STYLE_SOLID, isRTL); } void diff --git a/layout/generic/nsHTMLContainerFrame.h b/layout/generic/nsHTMLContainerFrame.h index 2d841cf14d5..ade0d50e253 100644 --- a/layout/generic/nsHTMLContainerFrame.h +++ b/layout/generic/nsHTMLContainerFrame.h @@ -170,6 +170,10 @@ protected: * i.e. negative offsets draws *below* * the baseline. * @param aSize the thickness of the line + * @param aDecoration which line will be painted + * i.e., NS_STYLE_TEXT_DECORATION_UNDERLINE or + * NS_STYLE_TEXT_DECORATION_OVERLINE or + * NS_STYLE_TEXT_DECORATION_LINE_THROUGH. */ virtual void PaintTextDecorationLine(nsIRenderingContext& aRenderingContext, nsPoint aPt, @@ -177,8 +181,9 @@ protected: nscolor aColor, nscoord aOffset, nscoord aAscent, - nscoord aSize); - + nscoord aSize, + const PRUint8 aDecoration); + friend class nsDisplayTextDecoration; }; diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 0958520725c..b0818fac00f 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -3691,7 +3691,7 @@ FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext, { gfxRect r = aRect.Intersect(aDirtyRect); // For now, we need to put this in pixel coordinates - float t2p = 1.0/aPresContext->AppUnitsPerDevPixel(); + float t2p = 1.0f / aPresContext->AppUnitsPerDevPixel(); aCtx->NewPath(); // pixel-snap aCtx->Rectangle(gfxRect(r.X()*t2p, r.Y()*t2p, r.Width()*t2p, r.Height()*t2p), PR_TRUE); @@ -3765,24 +3765,35 @@ nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect, return; gfxFont::Metrics fontMetrics = GetFontMetrics(aProvider.GetFontGroup()); - gfxFloat pix2app = mTextRun->GetAppUnitsPerDevUnit(); + gfxFloat a2p = 1.0 / aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); + + // XXX aFramePt is in AppUnits, shouldn't it be nsFloatPoint? + gfxPoint pt(aFramePt.x * a2p, aFramePt.y * a2p); + gfxSize size(GetRect().width * a2p, 0); + gfxFloat ascent = mAscent * a2p; if (decorations & NS_FONT_DECORATION_OVERLINE) { - FillClippedRect(aCtx, aTextPaintStyle.PresContext(), overColor, aDirtyRect, - gfxRect(aFramePt.x, aFramePt.y, - GetRect().width, NS_round(fontMetrics.underlineSize)*pix2app)); + size.height = fontMetrics.underlineSize; + nsCSSRendering::PaintDecorationLine( + aCtx, overColor, pt, size, ascent, ascent, size.height, + NS_STYLE_TEXT_DECORATION_OVERLINE, NS_STYLE_BORDER_STYLE_SOLID, + mTextRun->IsRightToLeft()); } if (decorations & NS_FONT_DECORATION_UNDERLINE) { - FillClippedRect(aCtx, aTextPaintStyle.PresContext(), underColor, aDirtyRect, - gfxRect(aFramePt.x, - GetSnappedBaselineY(aCtx, aFramePt.y) - NS_round(fontMetrics.underlineOffset)*pix2app, - GetRect().width, NS_round(fontMetrics.underlineSize)*pix2app)); + size.height = fontMetrics.underlineSize; + gfxFloat offset = fontMetrics.underlineOffset; + nsCSSRendering::PaintDecorationLine( + aCtx, underColor, pt, size, ascent, offset, size.height, + NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_SOLID, + mTextRun->IsRightToLeft()); } if (decorations & NS_FONT_DECORATION_LINE_THROUGH) { - FillClippedRect(aCtx, aTextPaintStyle.PresContext(), strikeColor, aDirtyRect, - gfxRect(aFramePt.x, - GetSnappedBaselineY(aCtx, aFramePt.y) - NS_round(fontMetrics.strikeoutOffset)*pix2app, - GetRect().width, NS_round(fontMetrics.strikeoutSize)*pix2app)); + size.height = fontMetrics.strikeoutSize; + gfxFloat offset = fontMetrics.strikeoutOffset; + nsCSSRendering::PaintDecorationLine( + aCtx, strikeColor, pt, size, ascent, offset, size.height, + NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_SOLID, + mTextRun->IsRightToLeft()); } } @@ -3795,21 +3806,20 @@ static const SelectionType SelectionTypesWithDecorations = nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT; static void DrawIMEUnderline(gfxContext* aContext, PRInt32 aIndex, - nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth, - const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics) + nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth, + gfxFloat aAscent, gfxFloat aSize, gfxFloat aOffset, PRBool aIsRTL) { - float p2t = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); nscolor color; float relativeSize; if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize)) return; - gfxFloat y = aBaselinePt.y - aFontMetrics.underlineOffset*p2t; - gfxFloat size = aFontMetrics.underlineSize*p2t; - FillClippedRect(aContext, aTextPaintStyle.PresContext(), - color, aDirtyRect, - gfxRect(aBaselinePt.x + size, y, - PR_MAX(0, aWidth - 2*size), relativeSize*size)); + gfxFloat actualSize = relativeSize * aSize; + gfxFloat width = PR_MAX(0, aWidth - 2.0 * aSize); + gfxPoint pt(aPt.x + 1.0, aPt.y); + nsCSSRendering::PaintDecorationLine( + aContext, color, pt, gfxSize(width, actualSize), aAscent, aOffset, aSize, + NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_SOLID, aIsRTL); } /** @@ -3817,40 +3827,41 @@ static void DrawIMEUnderline(gfxContext* aContext, PRInt32 aIndex, * drawing text decoration for selections. */ static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType, - nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth, - const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics) + nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth, + gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics, PRBool aIsRTL) { - float p2t = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); - float t2p = 1/p2t; + gfxSize size(aWidth, aFontMetrics.underlineSize); + gfxFloat offset = aFontMetrics.underlineOffset; switch (aType) { case nsISelectionController::SELECTION_SPELLCHECK: { - gfxFloat y = aBaselinePt.y*t2p - aFontMetrics.underlineOffset; - aContext->SetDash(gfxContext::gfxLineDotted); - aContext->SetColor(gfxRGBA(1.0, 0.0, 0.0)); - aContext->SetLineWidth(1.0); - aContext->NewPath(); - aContext->Line(gfxPoint(aBaselinePt.x*t2p, y), - gfxPoint((aBaselinePt.x + aWidth)*t2p, y)); - aContext->Stroke(); + nsCSSRendering::PaintDecorationLine( + aContext, NS_RGB(255,0,0), + aPt, size, aAscent, aFontMetrics.underlineOffset, size.height, + NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_DOTTED, + aIsRTL); break; } case nsISelectionController::SELECTION_IME_RAWINPUT: - DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexRawInput, aTextPaintStyle, - aBaselinePt, aWidth, aDirtyRect, aFontMetrics); + DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexRawInput, + aTextPaintStyle, aPt, aWidth, aAscent, size.height, + aFontMetrics.underlineOffset, aIsRTL); break; case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT: - DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelRawText, aTextPaintStyle, - aBaselinePt, aWidth, aDirtyRect, aFontMetrics); + DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelRawText, + aTextPaintStyle, aPt, aWidth, aAscent, size.height, + aFontMetrics.underlineOffset, aIsRTL); break; case nsISelectionController::SELECTION_IME_CONVERTEDTEXT: - DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexConvText, aTextPaintStyle, - aBaselinePt, aWidth, aDirtyRect, aFontMetrics); + DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexConvText, + aTextPaintStyle, aPt, aWidth, aAscent, size.height, + aFontMetrics.underlineOffset, aIsRTL); break; case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT: - DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelConvText, aTextPaintStyle, - aBaselinePt, aWidth, aDirtyRect, aFontMetrics); + DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelConvText, + aTextPaintStyle, aPt, aWidth, aAscent, size.height, + aFontMetrics.underlineOffset, aIsRTL); break; default: @@ -4137,10 +4148,14 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, gfxFloat advance = hyphenWidth + mTextRun->GetAdvanceWidth(offset, length, &aProvider); if (type == aSelectionType) { - gfxFloat x = aTextBaselinePt.x + xOffset - (mTextRun->IsRightToLeft() ? advance : 0); + gfxFloat a2p = 1.0 / aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); + // XXX aTextBaselinePt is in AppUnits, shouldn't it be nsFloatPoint? + gfxPoint pt((aTextBaselinePt.x + xOffset) * a2p, + (aTextBaselinePt.y - mAscent) * a2p); + gfxFloat width = PR_ABS(advance) * a2p; DrawSelectionDecorations(aCtx, aSelectionType, aTextPaintStyle, - gfxPoint(x, aTextBaselinePt.y), advance, - aDirtyRect, decorationMetrics); + pt, width, mAscent * a2p, decorationMetrics, + mTextRun->IsRightToLeft()); } iterator.UpdateWithAdvance(advance); } diff --git a/layout/mathml/base/src/Makefile.in b/layout/mathml/base/src/Makefile.in index 2d5b9f21025..f17ad3e1cd0 100644 --- a/layout/mathml/base/src/Makefile.in +++ b/layout/mathml/base/src/Makefile.in @@ -55,6 +55,7 @@ REQUIRES = xpcom \ dom \ content \ gfx \ + thebes \ widget \ view \ webshell \ diff --git a/layout/tables/Makefile.in b/layout/tables/Makefile.in index 3a8d15e8e80..3e770aacd4e 100644 --- a/layout/tables/Makefile.in +++ b/layout/tables/Makefile.in @@ -51,6 +51,7 @@ REQUIRES = xpcom \ dom \ content \ gfx \ + thebes \ widget \ locale \ view \ diff --git a/layout/xul/base/src/grid/Makefile.in b/layout/xul/base/src/grid/Makefile.in index cb651f05b54..c5a8efd2704 100644 --- a/layout/xul/base/src/grid/Makefile.in +++ b/layout/xul/base/src/grid/Makefile.in @@ -49,6 +49,7 @@ REQUIRES = xpcom \ string \ content \ gfx \ + thebes \ widget \ locale \ view \ diff --git a/layout/xul/base/src/nsTextBoxFrame.cpp b/layout/xul/base/src/nsTextBoxFrame.cpp index 40d53d8ea14..e40902aa8dc 100644 --- a/layout/xul/base/src/nsTextBoxFrame.cpp +++ b/layout/xul/base/src/nsTextBoxFrame.cpp @@ -69,6 +69,7 @@ #include "nsUnicharUtils.h" #include "nsContentUtils.h" #include "nsDisplayList.h" +#include "nsCSSRendering.h" #ifdef IBMBIDI #include "nsBidiUtils.h" @@ -401,22 +402,48 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext, presContext->DeviceContext()->GetMetricsFor(fontStyle->mFont, *getter_AddRefs(fontMet)); fontMet->GetMaxAscent(baseline); + PRBool isRTL = vis->mDirection == NS_STYLE_DIRECTION_RTL; + nsRefPtr ctx = (gfxContext*) + aRenderingContext.GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); + gfxFloat a2p = 1.0 / presContext->AppUnitsPerDevPixel(); + gfxPoint pt(textRect.x * a2p, textRect.y * a2p); + gfxFloat width = textRect.width * a2p; + gfxFloat baselinePixel = baseline * a2p; if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) { fontMet->GetUnderline(offset, size); + gfxFloat offsetPixel = offset * a2p; + gfxFloat sizePixel = size * a2p; if (decorations & NS_FONT_DECORATION_OVERLINE) { - aRenderingContext.SetColor(overColor); - aRenderingContext.FillRect(textRect.x, textRect.y, textRect.width, size); + nsCSSRendering::PaintDecorationLine(ctx, overColor, + pt, gfxSize(width, sizePixel), + baselinePixel, baselinePixel, + sizePixel, + NS_STYLE_TEXT_DECORATION_OVERLINE, + NS_STYLE_BORDER_STYLE_SOLID, + isRTL); } if (decorations & NS_FONT_DECORATION_UNDERLINE) { - aRenderingContext.SetColor(underColor); - aRenderingContext.FillRect(textRect.x, textRect.y + baseline - offset, textRect.width, size); + nsCSSRendering::PaintDecorationLine(ctx, underColor, + pt, gfxSize(width, sizePixel), + baselinePixel, offsetPixel, + sizePixel, + NS_STYLE_TEXT_DECORATION_UNDERLINE, + NS_STYLE_BORDER_STYLE_SOLID, + isRTL); } } if (decorations & NS_FONT_DECORATION_LINE_THROUGH) { fontMet->GetStrikeout(offset, size); - aRenderingContext.SetColor(strikeColor); - aRenderingContext.FillRect(textRect.x, textRect.y + baseline - offset, textRect.width, size); + gfxFloat offsetPixel = offset * a2p; + gfxFloat sizePixel = size * a2p; + nsCSSRendering::PaintDecorationLine(ctx, underColor, + pt, gfxSize(width, sizePixel), + baselinePixel, offsetPixel, + sizePixel, + NS_STYLE_TEXT_DECORATION_LINE_THROUGH, + NS_STYLE_BORDER_STYLE_SOLID, + isRTL); } aRenderingContext.SetFont(fontStyle->mFont, nsnull); diff --git a/layout/xul/base/src/tree/src/Makefile.in b/layout/xul/base/src/tree/src/Makefile.in index cd46d7fce69..ca67702648f 100644 --- a/layout/xul/base/src/tree/src/Makefile.in +++ b/layout/xul/base/src/tree/src/Makefile.in @@ -51,6 +51,7 @@ REQUIRES = xpcom \ content \ xul \ gfx \ + thebes \ widget \ locale \ view \