Bug 365336 text-decoration width should be rounded to the device pixels r+sr=roc

This commit is contained in:
masayuki@d-toybox.com 2007-08-06 01:15:00 -07:00
Родитель 8f9c022bd3
Коммит 33b8312a5c
12 изменённых файлов: 305 добавлений и 66 удалений

Просмотреть файл

@ -4355,3 +4355,128 @@ nsCSSRendering::DrawTableBorderSegment(nsIRenderingContext& aContext,
// End table border-collapsing section // 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!");
}

Просмотреть файл

@ -41,6 +41,7 @@
#define nsCSSRendering_h___ #define nsCSSRendering_h___
#include "nsIRenderingContext.h" #include "nsIRenderingContext.h"
#include "gfxContext.h"
struct nsPoint; struct nsPoint;
class nsStyleContext; class nsStyleContext;
class nsPresContext; class nsPresContext;
@ -198,6 +199,45 @@ public:
*/ */
static nscolor TransformColor(nscolor aMapColor,PRBool aNoBackGround); 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: protected:
static void PaintBackgroundColor(nsPresContext* aPresContext, static void PaintBackgroundColor(nsPresContext* aPresContext,

Просмотреть файл

@ -88,6 +88,7 @@
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsContentErrors.h" #include "nsContentErrors.h"
#include "nsCSSAnonBoxes.h" #include "nsCSSAnonBoxes.h"
#include "nsCSSRendering.h"
#ifdef IBMBIDI #ifdef IBMBIDI
#include "nsBidiPresUtils.h" #include "nsBidiPresUtils.h"
@ -5663,9 +5664,9 @@ nsBlockFrame::PaintTextDecorationLine(nsIRenderingContext& aRenderingContext,
nscolor aColor, nscolor aColor,
nscoord aOffset, nscoord aOffset,
nscoord aAscent, 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?"); NS_ASSERTION(!aLine->IsBlock(), "Why did we ask for decorations on a block?");
nscoord start = aLine->mBounds.x; nscoord start = aLine->mBounds.x;
@ -5698,9 +5699,18 @@ nsBlockFrame::PaintTextDecorationLine(nsIRenderingContext& aRenderingContext,
// Only paint if we have a positive width // Only paint if we have a positive width
if (width > 0) { if (width > 0) {
aRenderingContext.FillRect(start + aPt.x, const nsStyleVisibility* visibility = GetStyleVisibility();
aLine->mBounds.y + aLine->GetAscent() - aOffset + aPt.y, PRBool isRTL = visibility->mDirection == NS_STYLE_DIRECTION_RTL;
width, aSize); nsRefPtr<gfxContext> 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);
} }
} }

Просмотреть файл

@ -316,7 +316,8 @@ protected:
nscolor aColor, nscolor aColor,
nscoord aOffset, nscoord aOffset,
nscoord aAscent, nscoord aAscent,
nscoord aSize); nscoord aSize,
const PRUint8 aDecoration);
void TryAllLines(nsLineList::iterator* aIterator, void TryAllLines(nsLineList::iterator* aIterator,
nsLineList::iterator* aEndIterator, nsLineList::iterator* aEndIterator,

Просмотреть файл

@ -67,6 +67,7 @@
#include "nsBlockFrame.h" #include "nsBlockFrame.h"
#include "nsLineBox.h" #include "nsLineBox.h"
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsCSSRendering.h"
class nsDisplayTextDecoration : public nsDisplayItem { class nsDisplayTextDecoration : public nsDisplayItem {
public: public:
@ -117,13 +118,16 @@ nsDisplayTextDecoration::Paint(nsDisplayListBuilder* aBuilder,
if (mDecoration != NS_STYLE_TEXT_DECORATION_LINE_THROUGH) { if (mDecoration != NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
fm->GetUnderline(offset, size); fm->GetUnderline(offset, size);
if (mDecoration == NS_STYLE_TEXT_DECORATION_UNDERLINE) { 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) { } 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 { } else {
fm->GetStrikeout(offset, size); 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, nscolor aColor,
nscoord aOffset, nscoord aOffset,
nscoord aAscent, nscoord aAscent,
nscoord aSize) nscoord aSize,
const PRUint8 aDecoration)
{ {
NS_ASSERTION(!aLine, "Should not have passed a linebox to a non-block frame"); NS_ASSERTION(!aLine, "Should not have passed a linebox to a non-block frame");
nsMargin bp = GetUsedBorderAndPadding(); nsMargin bp = GetUsedBorderAndPadding();
@ -213,10 +218,17 @@ nsHTMLContainerFrame::PaintTextDecorationLine(
bp.side(side) = 0; 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; nscoord innerWidth = mRect.width - bp.left - bp.right;
aRenderingContext.FillRect(bp.left + aPt.x, nsRefPtr<gfxContext> ctx = (gfxContext*)
bp.top + aAscent - aOffset + aPt.y, innerWidth, aSize); 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 void

Просмотреть файл

@ -170,6 +170,10 @@ protected:
* i.e. negative offsets draws *below* * i.e. negative offsets draws *below*
* the baseline. * the baseline.
* @param aSize the thickness of the line * @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, virtual void PaintTextDecorationLine(nsIRenderingContext& aRenderingContext,
nsPoint aPt, nsPoint aPt,
@ -177,8 +181,9 @@ protected:
nscolor aColor, nscolor aColor,
nscoord aOffset, nscoord aOffset,
nscoord aAscent, nscoord aAscent,
nscoord aSize); nscoord aSize,
const PRUint8 aDecoration);
friend class nsDisplayTextDecoration; friend class nsDisplayTextDecoration;
}; };

Просмотреть файл

@ -3691,7 +3691,7 @@ FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext,
{ {
gfxRect r = aRect.Intersect(aDirtyRect); gfxRect r = aRect.Intersect(aDirtyRect);
// For now, we need to put this in pixel coordinates // For now, we need to put this in pixel coordinates
float t2p = 1.0/aPresContext->AppUnitsPerDevPixel(); float t2p = 1.0f / aPresContext->AppUnitsPerDevPixel();
aCtx->NewPath(); aCtx->NewPath();
// pixel-snap // pixel-snap
aCtx->Rectangle(gfxRect(r.X()*t2p, r.Y()*t2p, r.Width()*t2p, r.Height()*t2p), PR_TRUE); 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; return;
gfxFont::Metrics fontMetrics = GetFontMetrics(aProvider.GetFontGroup()); 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) { if (decorations & NS_FONT_DECORATION_OVERLINE) {
FillClippedRect(aCtx, aTextPaintStyle.PresContext(), overColor, aDirtyRect, size.height = fontMetrics.underlineSize;
gfxRect(aFramePt.x, aFramePt.y, nsCSSRendering::PaintDecorationLine(
GetRect().width, NS_round(fontMetrics.underlineSize)*pix2app)); 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) { if (decorations & NS_FONT_DECORATION_UNDERLINE) {
FillClippedRect(aCtx, aTextPaintStyle.PresContext(), underColor, aDirtyRect, size.height = fontMetrics.underlineSize;
gfxRect(aFramePt.x, gfxFloat offset = fontMetrics.underlineOffset;
GetSnappedBaselineY(aCtx, aFramePt.y) - NS_round(fontMetrics.underlineOffset)*pix2app, nsCSSRendering::PaintDecorationLine(
GetRect().width, NS_round(fontMetrics.underlineSize)*pix2app)); 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) { if (decorations & NS_FONT_DECORATION_LINE_THROUGH) {
FillClippedRect(aCtx, aTextPaintStyle.PresContext(), strikeColor, aDirtyRect, size.height = fontMetrics.strikeoutSize;
gfxRect(aFramePt.x, gfxFloat offset = fontMetrics.strikeoutOffset;
GetSnappedBaselineY(aCtx, aFramePt.y) - NS_round(fontMetrics.strikeoutOffset)*pix2app, nsCSSRendering::PaintDecorationLine(
GetRect().width, NS_round(fontMetrics.strikeoutSize)*pix2app)); 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; nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT;
static void DrawIMEUnderline(gfxContext* aContext, PRInt32 aIndex, static void DrawIMEUnderline(gfxContext* aContext, PRInt32 aIndex,
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth, nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth,
const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics) gfxFloat aAscent, gfxFloat aSize, gfxFloat aOffset, PRBool aIsRTL)
{ {
float p2t = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel();
nscolor color; nscolor color;
float relativeSize; float relativeSize;
if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize)) if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize))
return; return;
gfxFloat y = aBaselinePt.y - aFontMetrics.underlineOffset*p2t; gfxFloat actualSize = relativeSize * aSize;
gfxFloat size = aFontMetrics.underlineSize*p2t; gfxFloat width = PR_MAX(0, aWidth - 2.0 * aSize);
FillClippedRect(aContext, aTextPaintStyle.PresContext(), gfxPoint pt(aPt.x + 1.0, aPt.y);
color, aDirtyRect, nsCSSRendering::PaintDecorationLine(
gfxRect(aBaselinePt.x + size, y, aContext, color, pt, gfxSize(width, actualSize), aAscent, aOffset, aSize,
PR_MAX(0, aWidth - 2*size), relativeSize*size)); 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. * drawing text decoration for selections.
*/ */
static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType, static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth, nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth,
const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics) gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics, PRBool aIsRTL)
{ {
float p2t = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); gfxSize size(aWidth, aFontMetrics.underlineSize);
float t2p = 1/p2t; gfxFloat offset = aFontMetrics.underlineOffset;
switch (aType) { switch (aType) {
case nsISelectionController::SELECTION_SPELLCHECK: { case nsISelectionController::SELECTION_SPELLCHECK: {
gfxFloat y = aBaselinePt.y*t2p - aFontMetrics.underlineOffset; nsCSSRendering::PaintDecorationLine(
aContext->SetDash(gfxContext::gfxLineDotted); aContext, NS_RGB(255,0,0),
aContext->SetColor(gfxRGBA(1.0, 0.0, 0.0)); aPt, size, aAscent, aFontMetrics.underlineOffset, size.height,
aContext->SetLineWidth(1.0); NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_DOTTED,
aContext->NewPath(); aIsRTL);
aContext->Line(gfxPoint(aBaselinePt.x*t2p, y),
gfxPoint((aBaselinePt.x + aWidth)*t2p, y));
aContext->Stroke();
break; break;
} }
case nsISelectionController::SELECTION_IME_RAWINPUT: case nsISelectionController::SELECTION_IME_RAWINPUT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexRawInput, aTextPaintStyle, DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexRawInput,
aBaselinePt, aWidth, aDirtyRect, aFontMetrics); aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset, aIsRTL);
break; break;
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT: case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelRawText, aTextPaintStyle, DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelRawText,
aBaselinePt, aWidth, aDirtyRect, aFontMetrics); aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset, aIsRTL);
break; break;
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT: case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexConvText, aTextPaintStyle, DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexConvText,
aBaselinePt, aWidth, aDirtyRect, aFontMetrics); aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset, aIsRTL);
break; break;
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT: case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelConvText, aTextPaintStyle, DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelConvText,
aBaselinePt, aWidth, aDirtyRect, aFontMetrics); aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset, aIsRTL);
break; break;
default: default:
@ -4137,10 +4148,14 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
gfxFloat advance = hyphenWidth + gfxFloat advance = hyphenWidth +
mTextRun->GetAdvanceWidth(offset, length, &aProvider); mTextRun->GetAdvanceWidth(offset, length, &aProvider);
if (type == aSelectionType) { 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, DrawSelectionDecorations(aCtx, aSelectionType, aTextPaintStyle,
gfxPoint(x, aTextBaselinePt.y), advance, pt, width, mAscent * a2p, decorationMetrics,
aDirtyRect, decorationMetrics); mTextRun->IsRightToLeft());
} }
iterator.UpdateWithAdvance(advance); iterator.UpdateWithAdvance(advance);
} }

Просмотреть файл

@ -55,6 +55,7 @@ REQUIRES = xpcom \
dom \ dom \
content \ content \
gfx \ gfx \
thebes \
widget \ widget \
view \ view \
webshell \ webshell \

Просмотреть файл

@ -51,6 +51,7 @@ REQUIRES = xpcom \
dom \ dom \
content \ content \
gfx \ gfx \
thebes \
widget \ widget \
locale \ locale \
view \ view \

Просмотреть файл

@ -49,6 +49,7 @@ REQUIRES = xpcom \
string \ string \
content \ content \
gfx \ gfx \
thebes \
widget \ widget \
locale \ locale \
view \ view \

Просмотреть файл

@ -69,6 +69,7 @@
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsDisplayList.h" #include "nsDisplayList.h"
#include "nsCSSRendering.h"
#ifdef IBMBIDI #ifdef IBMBIDI
#include "nsBidiUtils.h" #include "nsBidiUtils.h"
@ -401,22 +402,48 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
presContext->DeviceContext()->GetMetricsFor(fontStyle->mFont, presContext->DeviceContext()->GetMetricsFor(fontStyle->mFont,
*getter_AddRefs(fontMet)); *getter_AddRefs(fontMet));
fontMet->GetMaxAscent(baseline); fontMet->GetMaxAscent(baseline);
PRBool isRTL = vis->mDirection == NS_STYLE_DIRECTION_RTL;
nsRefPtr<gfxContext> 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)) { if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) {
fontMet->GetUnderline(offset, size); fontMet->GetUnderline(offset, size);
gfxFloat offsetPixel = offset * a2p;
gfxFloat sizePixel = size * a2p;
if (decorations & NS_FONT_DECORATION_OVERLINE) { if (decorations & NS_FONT_DECORATION_OVERLINE) {
aRenderingContext.SetColor(overColor); nsCSSRendering::PaintDecorationLine(ctx, overColor,
aRenderingContext.FillRect(textRect.x, textRect.y, textRect.width, size); pt, gfxSize(width, sizePixel),
baselinePixel, baselinePixel,
sizePixel,
NS_STYLE_TEXT_DECORATION_OVERLINE,
NS_STYLE_BORDER_STYLE_SOLID,
isRTL);
} }
if (decorations & NS_FONT_DECORATION_UNDERLINE) { if (decorations & NS_FONT_DECORATION_UNDERLINE) {
aRenderingContext.SetColor(underColor); nsCSSRendering::PaintDecorationLine(ctx, underColor,
aRenderingContext.FillRect(textRect.x, textRect.y + baseline - offset, textRect.width, size); 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) { if (decorations & NS_FONT_DECORATION_LINE_THROUGH) {
fontMet->GetStrikeout(offset, size); fontMet->GetStrikeout(offset, size);
aRenderingContext.SetColor(strikeColor); gfxFloat offsetPixel = offset * a2p;
aRenderingContext.FillRect(textRect.x, textRect.y + baseline - offset, textRect.width, size); 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); aRenderingContext.SetFont(fontStyle->mFont, nsnull);

Просмотреть файл

@ -51,6 +51,7 @@ REQUIRES = xpcom \
content \ content \
xul \ xul \
gfx \ gfx \
thebes \
widget \ widget \
locale \ locale \
view \ view \