Bug 338209 Make spellchecker use thicker wavy underlines instead of dotted underlines r+sr=roc

This commit is contained in:
Masayuki Nakano 2009-04-03 16:26:28 +09:00
parent d71fb0a959
commit 0066bb8330
29 changed files with 1469 additions and 292 deletions

View File

@ -88,7 +88,12 @@ nsContentEventHandler::Init(nsQueryContentEvent* aEvent)
if (!mPresShell)
return NS_ERROR_NOT_AVAILABLE;
nsresult rv = mPresShell->GetSelectionForCopy(getter_AddRefs(mSelection));
// If text frame which has overflowing selection underline is dirty,
// we need to flush the pending reflow here.
nsresult rv = mPresShell->FlushPendingNotifications(Flush_Layout);
NS_ENSURE_SUCCESS(rv, rv);
rv = mPresShell->GetSelectionForCopy(getter_AddRefs(mSelection));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(mSelection,
"GetSelectionForCopy succeeded, but the result is null");

View File

@ -88,6 +88,7 @@ DIRS += tools/pageloader
ifndef MOZ_ENABLE_LIBXUL
TOOL_DIRS += html/tests
endif
TOOL_DIRS += reftests/fonts reftests/fonts/mplus
endif
include $(topsrcdir)/config/rules.mk

View File

@ -334,13 +334,6 @@ static nscolor MakeBevelColor(PRIntn whichSide, PRUint8 style,
nscolor aBackgroundColor,
nscolor aBorderColor);
static gfxRect GetTextDecorationRectInternal(const gfxPoint& aPt,
const gfxSize& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const PRUint8 aDecoration,
const PRUint8 aStyle);
/* Returns FALSE iff all returned aTwipsRadii == 0, TRUE otherwise */
static PRBool GetBorderRadiusTwips(const nsStyleCorners& aBorderRadius,
const nscoord& aFrameWidth,
@ -2507,6 +2500,8 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
const PRUint8 aDecoration,
const PRUint8 aStyle)
{
NS_ASSERTION(aStyle != DECORATION_STYLE_NONE, "aStyle is none");
gfxRect rect =
GetTextDecorationRectInternal(aPt, aLineSize, aAscent, aOffset,
aDecoration, aStyle);
@ -2528,23 +2523,27 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
nsRefPtr<gfxPattern> oldPattern;
switch (aStyle) {
case NS_STYLE_BORDER_STYLE_SOLID:
case NS_STYLE_BORDER_STYLE_DOUBLE:
case DECORATION_STYLE_SOLID:
case DECORATION_STYLE_DOUBLE:
oldLineWidth = aGfxContext->CurrentLineWidth();
oldPattern = aGfxContext->GetPattern();
break;
case NS_STYLE_BORDER_STYLE_DASHED: {
case DECORATION_STYLE_DASHED: {
aGfxContext->Save();
contextIsSaved = PR_TRUE;
aGfxContext->Clip(rect);
gfxFloat dashWidth = lineHeight * DOT_LENGTH * DASH_LENGTH;
gfxFloat dash[2] = { dashWidth, dashWidth };
aGfxContext->SetLineCap(gfxContext::LINE_CAP_BUTT);
aGfxContext->SetDash(dash, 2, 0.0);
// We should continue to draw the last dash even if it is not in the rect.
rect.size.width += dashWidth;
break;
}
case NS_STYLE_BORDER_STYLE_DOTTED: {
case DECORATION_STYLE_DOTTED: {
aGfxContext->Save();
contextIsSaved = PR_TRUE;
aGfxContext->Clip(rect);
gfxFloat dashWidth = lineHeight * DOT_LENGTH;
gfxFloat dash[2];
if (lineHeight > 2.0) {
@ -2556,8 +2555,23 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
dash[1] = dashWidth;
}
aGfxContext->SetDash(dash, 2, 0.0);
// We should continue to draw the last dot even if it is not in the rect.
rect.size.width += dashWidth;
break;
}
case DECORATION_STYLE_WAVY:
aGfxContext->Save();
contextIsSaved = PR_TRUE;
aGfxContext->Clip(rect);
if (lineHeight > 2.0) {
aGfxContext->SetAntialiasMode(gfxContext::MODE_COVERAGE);
} else {
// Don't use anti-aliasing here. Because looks like lighter color wavy
// line at this case. And probably, users don't think the
// non-anti-aliased wavy line is not pretty.
aGfxContext->SetAntialiasMode(gfxContext::MODE_ALIASED);
}
break;
default:
NS_ERROR("Invalid style value!");
return;
@ -2569,13 +2583,27 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
aGfxContext->SetColor(gfxRGBA(aColor));
aGfxContext->SetLineWidth(lineHeight);
switch (aStyle) {
case NS_STYLE_BORDER_STYLE_SOLID:
case DECORATION_STYLE_SOLID:
aGfxContext->NewPath();
aGfxContext->MoveTo(rect.TopLeft());
aGfxContext->LineTo(rect.TopRight());
aGfxContext->Stroke();
break;
case NS_STYLE_BORDER_STYLE_DOUBLE:
case DECORATION_STYLE_DOUBLE:
/**
* We are drawing double line as:
*
* +-------------------------------------------+
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| ^
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | lineHeight
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| v
* | |
* | |
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| ^
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | lineHeight
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| v
* +-------------------------------------------+
*/
aGfxContext->NewPath();
aGfxContext->MoveTo(rect.TopLeft());
aGfxContext->LineTo(rect.TopRight());
@ -2584,13 +2612,72 @@ nsCSSRendering::PaintDecorationLine(gfxContext* aGfxContext,
aGfxContext->LineTo(rect.BottomRight());
aGfxContext->Stroke();
break;
case NS_STYLE_BORDER_STYLE_DOTTED:
case NS_STYLE_BORDER_STYLE_DASHED:
case DECORATION_STYLE_DOTTED:
case DECORATION_STYLE_DASHED:
aGfxContext->NewPath();
aGfxContext->MoveTo(rect.TopLeft());
aGfxContext->LineTo(rect.TopRight());
aGfxContext->Stroke();
break;
case DECORATION_STYLE_WAVY: {
/**
* We are drawing wavy line as:
*
* P: Path, X: Painted pixel
*
* +---------------------------------------+
* XX|X XXXXXX XXXXXX |
* PP|PX XPPPPPPX XPPPPPPX | ^
* XX|XPX XPXXXXXXPX XPXXXXXXPX| |
* | XPX XPX XPX XPX XP|X |adv
* | XPXXXXXXPX XPXXXXXXPX X|PX |
* | XPPPPPPX XPPPPPPX |XPX v
* | XXXXXX XXXXXX | XX
* +---------------------------------------+
* <---><---> ^
* adv flatLengthAtVertex rightMost
*
* 1. Always starts from top-left of the drawing area, however, we need
* to draw the line from outside of the rect. Because the start
* point of the line is not good style if we draw from inside it.
* 2. First, draw horizontal line from outside the rect to top-left of
* the rect;
* 3. Goes down to bottom of the area at 45 degrees.
* 4. Slides to right horizontaly, see |flatLengthAtVertex|.
* 5. Goes up to top of the area at 45 degrees.
* 6. Slides to right horizontaly.
* 7. Repeat from 2 until reached to right-most edge of the area.
*/
rect.pos.x += lineHeight / 2.0;
aGfxContext->NewPath();
gfxPoint pt(rect.pos);
gfxFloat rightMost = pt.x + rect.Width() + lineHeight;
gfxFloat adv = rect.Height() - lineHeight;
gfxFloat flatLengthAtVertex = PR_MAX((lineHeight - 1.0) * 2.0, 1.0);
pt.x -= lineHeight;
aGfxContext->MoveTo(pt); // 1
pt.x = rect.pos.x;
aGfxContext->LineTo(pt); // 2
PRBool goDown = PR_TRUE;
while (pt.x < rightMost) {
pt.x += adv;
pt.y += goDown ? adv : -adv;
aGfxContext->LineTo(pt); // 3 and 5
pt.x += flatLengthAtVertex;
aGfxContext->LineTo(pt); // 4 and 6
goDown = !goDown;
}
aGfxContext->Stroke();
break;
}
default:
NS_ERROR("Invalid style value!");
break;
@ -2613,6 +2700,7 @@ nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext,
const PRUint8 aStyle)
{
NS_ASSERTION(aPresContext, "aPresContext is null");
NS_ASSERTION(aStyle != DECORATION_STYLE_NONE, "aStyle is none");
gfxRect rect =
GetTextDecorationRectInternal(gfxPoint(0, 0), aLineSize, aAscent, aOffset,
@ -2626,42 +2714,81 @@ nsCSSRendering::GetTextDecorationRect(nsPresContext* aPresContext,
return r;
}
static gfxRect
GetTextDecorationRectInternal(const gfxPoint& aPt,
const gfxSize& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const PRUint8 aDecoration,
const PRUint8 aStyle)
gfxRect
nsCSSRendering::GetTextDecorationRectInternal(const gfxPoint& aPt,
const gfxSize& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const PRUint8 aDecoration,
const PRUint8 aStyle)
{
NS_ASSERTION(aStyle <= DECORATION_STYLE_WAVY, "Invalid aStyle value");
if (aStyle == DECORATION_STYLE_NONE)
return gfxRect(0, 0, 0, 0);
gfxRect r;
r.pos.x = NS_floor(aPt.x + 0.5);
r.size.width = NS_round(aLineSize.width);
gfxFloat basesize = NS_round(aLineSize.height);
basesize = PR_MAX(basesize, 1.0);
r.size.height = basesize;
if (aStyle == NS_STYLE_BORDER_STYLE_DOUBLE) {
gfxFloat gap = NS_round(basesize / 2.0);
gfxFloat lineHeight = NS_round(aLineSize.height);
lineHeight = PR_MAX(lineHeight, 1.0);
gfxFloat underlineOffsetAdjust = 0.0;
r.size.height = lineHeight;
if (aStyle == DECORATION_STYLE_DOUBLE) {
/**
* We will draw double line as:
*
* +-------------------------------------------+
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| ^
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | lineHeight
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| v
* | | ^
* | | | gap
* | | v
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| ^
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| | lineHeight
* |XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX| v
* +-------------------------------------------+
*/
gfxFloat gap = NS_round(lineHeight / 2.0);
gap = PR_MAX(gap, 1.0);
r.size.height = basesize * 2.0 + gap;
} else {
r.size.height = basesize;
r.size.height = lineHeight * 2.0 + gap;
} else if (aStyle == DECORATION_STYLE_WAVY) {
/**
* We will draw wavy line as:
*
* +-------------------------------------------+
* |XXXXX XXXXXX XXXXXX | ^
* |XXXXXX XXXXXXXX XXXXXXXX | | lineHeight
* |XXXXXXX XXXXXXXXXX XXXXXXXXXX| v
* | XXX XXX XXX XXX XX|
* | XXXXXXXXXX XXXXXXXXXX X|
* | XXXXXXXX XXXXXXXX |
* | XXXXXX XXXXXX |
* +-------------------------------------------+
*/
r.size.height = lineHeight > 2.0 ? lineHeight * 4.0 : lineHeight * 3.0;
// If this is underline, the middle of the rect should be aligned to the
// specified underline offset. So, wavy line's top edge can overlap to
// baseline. Because even if the wavy line overlaps the baseline of the
// text, that shouldn't cause unreadability.
underlineOffsetAdjust = r.Height() / 2.0;
}
gfxFloat baseline = NS_floor(aPt.y + aAscent + 0.5);
gfxFloat offset = 0;
gfxFloat offset = 0.0;
switch (aDecoration) {
case NS_STYLE_TEXT_DECORATION_UNDERLINE:
offset = aOffset;
offset = aOffset + underlineOffsetAdjust;
break;
case NS_STYLE_TEXT_DECORATION_OVERLINE:
offset = aOffset - basesize + r.Height();
offset = aOffset - lineHeight + r.Height();
break;
case NS_STYLE_TEXT_DECORATION_LINE_THROUGH: {
gfxFloat extra = NS_floor(r.Height() / 2.0 + 0.5);
extra = PR_MAX(extra, basesize);
offset = aOffset - basesize + extra;
extra = PR_MAX(extra, lineHeight);
offset = aOffset - lineHeight + extra;
break;
}
default:

View File

@ -202,6 +202,15 @@ struct nsCSSRendering {
PRUint8 aEndBevelSide = 0,
nscoord aEndBevelOffset = 0);
enum {
DECORATION_STYLE_NONE = 0,
DECORATION_STYLE_SOLID = 1,
DECORATION_STYLE_DOTTED = 2,
DECORATION_STYLE_DASHED = 3,
DECORATION_STYLE_DOUBLE = 4,
DECORATION_STYLE_WAVY = 5
};
/**
* Function for painting the decoration lines for the text.
* NOTE: aPt, aLineSize, aAscent and aOffset are non-rounded device pixels,
@ -220,11 +229,8 @@ struct nsCSSRendering {
* 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.
* @param aStyle the style of the decoration line (See above
* enum names).
*/
static void PaintDecorationLine(gfxContext* aGfxContext,
const nscolor aColor,
@ -251,11 +257,8 @@ struct nsCSSRendering {
* 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.
* @param aStyle the style of the decoration line (See above
* enum names).
* output:
* @return the decoration line rect for the input,
* the each values are app units.
@ -266,6 +269,14 @@ struct nsCSSRendering {
const gfxFloat aOffset,
const PRUint8 aDecoration,
const PRUint8 aStyle);
protected:
static gfxRect GetTextDecorationRectInternal(const gfxPoint& aPt,
const gfxSize& aLineSize,
const gfxFloat aAscent,
const gfxFloat aOffset,
const PRUint8 aDecoration,
const PRUint8 aStyle);
};
/*

View File

@ -72,6 +72,7 @@ _TEST_FILES = \
test_bug435293-skew.html \
test_printpreview.html \
test_bug482976.html \
decoration_line_rendering.js \
$(NULL)
# test_bug396024.html is currently disabled because it interacts badly with
# the "You can't print-preview while the page is loading" dialog.

View File

@ -0,0 +1,180 @@
function addPoint(aSVGElement, aPolylineElement, aX, aY) {
var pt = aSVGElement.createSVGPoint();
pt.x = aX;
pt.y = aY;
aPolylineElement.points.appendItem(pt);
}
function round(aFloat)
{
return aFloat >= 0.0 ? Math.floor(aFloat + 0.5) : Math.ceil(aFloat - 0.5);
}
const kDecorationStyleNone = 0;
const kDecorationStyleSolid = 1;
const kDecorationStyleDotted = 2;
const kDecorationStyleDashed = 3;
const kDecorationStyleDouble = 4;
const kDecorationStyleWavy = 5;
const kDotLength = 1.0;
const kDashLength = 3.0;
const kSVGNS = "http://www.w3.org/2000/svg";
// XXX following functions only support to draw underline now.
function drawDecorationLine(aDocument, aColor, aPt, aLineSize, aAscent, aOffset, aStyle)
{
var rect = getTextDecorationRect(aPt, aLineSize, aAscent, aOffset, aStyle);
if (rect.width == 0 || rect.height == 0)
return;
var root = aDocument.documentElement;
var container = aDocument.createElementNS(kSVGNS, "svg");
root.appendChild(container);
var line1 = aDocument.createElementNS(kSVGNS, "polyline");
var line2;
var style = "position: absolute;";
style += "left: " + rect.x + "px;";
style += "top: " + rect.y + "px;";
style += "width: " + rect.width + "px;";
style += "height: " + rect.height + "px;";
container.setAttribute("style", style);
rect.x = rect.y = 0;
var lineHeight = Math.max(round(aLineSize.height), 1.0);
switch (aStyle) {
case kDecorationStyleDouble:
line2 = aDocument.createElementNS(kSVGNS, "polyline");
container.appendChild(line2);
case kDecorationStyleSolid:
container.appendChild(line1);
break;
case kDecorationStyleDashed:
container.appendChild(line1);
var dashWidth = lineHeight * kDotLength * kDashLength;
var dash = "stroke-dasharray: " + dashWidth + ", " + dashWidth + ";";
var lineCap = "stroke-linecap: butt;"
line1.setAttribute("style", dash + lineCap);
rect.width += dashWidth;
break;
case kDecorationStyleDotted:
container.appendChild(line1);
var dashWidth = lineHeight * kDotLength;
var dash = "stroke-dasharray: ";
var lineCap = "";
if (lineHeight > 2.0) {
dash += "0.0, " + dashWidth * 2.0 + ";";
lineCap = "stroke-linecap: round;";
} else {
dash += dashWidth + ", " + dashWidth + ";";
}
rect.width += dashWidth;
line1.setAttribute("style", dash + lineCap);
break;
case kDecorationStyleWavy:
container.appendChild(line1);
if (lineHeight > 2.0) {
//
} else {
line1.setAttribute("shape-rendering", "optimizeSpeed");
}
break;
}
rect.y += lineHeight / 2;
line1.setAttribute("fill", "none");
line1.setAttribute("stroke", aColor);
line1.setAttribute("stroke-width", lineHeight);
if (line2) {
line2.setAttribute("fill", "none");
line2.setAttribute("stroke", aColor);
line2.setAttribute("stroke-width", lineHeight);
}
switch (aStyle) {
case kDecorationStyleSolid:
addPoint(container, line1, rect.x, rect.y);
addPoint(container, line1, rect.x + rect.width, rect.y);
break;
case kDecorationStyleDouble:
addPoint(container, line1, rect.x, rect.y);
addPoint(container, line1, rect.x + rect.width, rect.y);
rect.height -= lineHeight;
addPoint(container, line2, rect.x, rect.y + rect.height);
addPoint(container, line2, rect.x + rect.width, rect.y + rect.height);
break;
case kDecorationStyleDotted:
case kDecorationStyleDashed:
addPoint(container, line1, rect.x, rect.y);
addPoint(container, line1, rect.x + rect.width, rect.y);
break;
case kDecorationStyleWavy:
rect.x += lineHeight / 2.0;
var pt = { x: rect.x, y: rect.y };
var rightMost = pt.x + rect.width + lineHeight;
var adv = rect.height - lineHeight;
var flatLengthAtVertex = Math.max((lineHeight - 1.0) * 2.0, 1.0);
var points = "";
pt.x -= lineHeight;
addPoint(container, line1, pt.x, pt.y);
pt.x = rect.x;
addPoint(container, line1, pt.x, pt.y);
var goDown = true;
while (pt.x < rightMost) {
pt.x += adv;
pt.y += goDown ? adv : -adv;
addPoint(container, line1, pt.x, pt.y);
pt.x += flatLengthAtVertex;
addPoint(container, line1, pt.x, pt.y);
goDown = !goDown;
}
break;
}
}
function getTextDecorationRect(aPt, aLineSize, aAscent, aOffset, aStyle)
{
if (aStyle == kDecorationStyleNone)
return { x: 0, y: 0, width: 0, height: 0 };
var r = {};
r.x = Math.floor(aPt.x + 0.5);
r.width = round(aLineSize.width);
var lineHeight = round(aLineSize.height);
lineHeight = Math.max(lineHeight, 1.0);
var underlineOffsetAdjust = 0.0;
r.height = lineHeight;
if (aStyle == kDecorationStyleDouble) {
var gap = round(lineHeight / 2.0);
gap = Math.max(gap, 1.0);
r.height = lineHeight * 2.0 + gap;
} else if (aStyle == kDecorationStyleWavy) {
r.height = lineHeight > 2.0 ? lineHeight * 4.0 : lineHeight * 3.0;
underlineOffsetAdjust = r.height / 2.0;
}
var baseline = Math.floor(aPt.y + aAscent + 0.5);
var offset = 0.0;
offset = aOffset + underlineOffsetAdjust;
r.y = baseline - Math.floor(offset + 0.5);
return r;
}

View File

@ -5987,7 +5987,7 @@ nsBlockFrame::PaintTextDecorationLine(gfxContext* aCtx,
nsCSSRendering::PaintDecorationLine(
aCtx, aColor, pt, size,
PresContext()->AppUnitsToGfxUnits(aLine->GetAscent()),
aOffset, aDecoration, NS_STYLE_BORDER_STYLE_SOLID);
aOffset, aDecoration, nsCSSRendering::DECORATION_STYLE_SOLID);
}
}

View File

@ -361,7 +361,7 @@ nsHTMLContainerFrame::PaintTextDecorationLine(
PresContext()->AppUnitsToGfxUnits(bp.top + aPt.y));
gfxSize size(PresContext()->AppUnitsToGfxUnits(innerWidth), aSize);
nsCSSRendering::PaintDecorationLine(aCtx, aColor, pt, size, aAscent, aOffset,
aDecoration, NS_STYLE_BORDER_STYLE_SOLID);
aDecoration, nsCSSRendering::DECORATION_STYLE_SOLID);
}
void

View File

@ -2655,63 +2655,3 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
}
aCombinedArea = combinedAreaResult;
}
void
nsLineLayout::CombineTextDecorations(nsPresContext* aPresContext,
PRUint8 aDecorations,
nsIFrame* aFrame,
nsRect& aCombinedArea,
nscoord aAscentOverride,
float aUnderlineSizeRatio)
{
if (!(aDecorations & (NS_STYLE_TEXT_DECORATION_UNDERLINE |
NS_STYLE_TEXT_DECORATION_OVERLINE |
NS_STYLE_TEXT_DECORATION_LINE_THROUGH)))
return;
nsCOMPtr<nsIFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
gfxFontGroup* fontGroup = tfm->GetThebesFontGroup();
gfxFont* firstFont = fontGroup->GetFontAt(0);
if (!firstFont)
return; // OOM
const gfxFont::Metrics& metrics = firstFont->GetMetrics();
gfxFloat ascent = aAscentOverride == 0 ? metrics.maxAscent :
aPresContext->AppUnitsToGfxUnits(aAscentOverride);
nsRect decorationArea;
if (aDecorations & (NS_STYLE_TEXT_DECORATION_UNDERLINE |
NS_STYLE_TEXT_DECORATION_OVERLINE)) {
gfxSize size(aPresContext->AppUnitsToGfxUnits(aCombinedArea.width),
metrics.underlineSize);
if (aDecorations & NS_STYLE_TEXT_DECORATION_OVERLINE) {
decorationArea =
nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent,
metrics.maxAscent, NS_STYLE_TEXT_DECORATION_OVERLINE,
NS_STYLE_BORDER_STYLE_SOLID);
aCombinedArea.UnionRect(aCombinedArea, decorationArea);
}
if (aDecorations & NS_STYLE_TEXT_DECORATION_UNDERLINE) {
aUnderlineSizeRatio = PR_MAX(aUnderlineSizeRatio, 1.0f);
size.height *= aUnderlineSizeRatio;
gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
decorationArea =
nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent,
underlineOffset,
NS_STYLE_TEXT_DECORATION_UNDERLINE,
NS_STYLE_BORDER_STYLE_SOLID);
aCombinedArea.UnionRect(aCombinedArea, decorationArea);
}
}
if (aDecorations & NS_STYLE_TEXT_DECORATION_LINE_THROUGH) {
gfxSize size(aPresContext->AppUnitsToGfxUnits(aCombinedArea.width),
metrics.strikeoutSize);
decorationArea =
nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent,
metrics.strikeoutOffset,
NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
NS_STYLE_BORDER_STYLE_SOLID);
aCombinedArea.UnionRect(aCombinedArea, decorationArea);
}
}

View File

@ -144,12 +144,6 @@ public:
*/
void RelativePositionFrames(nsRect& aCombinedArea);
static void CombineTextDecorations(nsPresContext* aPresContext,
PRUint8 aDecorations,
nsIFrame* aFrame,
nsRect& aCombinedArea,
nscoord aAscentOverride = 0,
float aUnderlineSizeRatio = 1.0f);
//----------------------------------------
// Supporting methods and data for flags

View File

@ -442,8 +442,10 @@ protected:
};
TextDecorations GetTextDecorations(nsPresContext* aPresContext);
PRBool HasSelectionOverflowingDecorations(nsPresContext* aPresContext,
float* aRatio = nsnull);
// 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.
PRBool CombineSelectionUnderlineRect(nsPresContext* aPresContext,
nsRect& aRect);
PRBool IsFloatingFirstLetterChild();
};

View File

@ -254,10 +254,17 @@ public:
nscolor* aForeColor,
nscolor* aBackColor);
// if this returns PR_FALSE, we don't need to draw underline.
PRBool GetIMEUnderline(PRInt32 aIndex,
nscolor* aLineColor,
float* aRelativeSize,
PRUint8* aStyle);
PRBool GetSelectionUnderlineForPaint(PRInt32 aIndex,
nscolor* aLineColor,
float* aRelativeSize,
PRUint8* aStyle);
// if this returns PR_FALSE, we don't need to draw underline.
static PRBool GetSelectionUnderline(nsPresContext* aPresContext,
PRInt32 aIndex,
nscolor* aLineColor,
float* aRelativeSize,
PRUint8* aStyle);
nsPresContext* PresContext() { return mPresContext; }
@ -265,9 +272,29 @@ public:
eIndexRawInput = 0,
eIndexSelRawText,
eIndexConvText,
eIndexSelConvText
eIndexSelConvText,
eIndexSpellChecker
};
static PRInt32 GetUnderlineStyleIndexForSelectionType(PRInt32 aSelectionType)
{
switch (aSelectionType) {
case nsISelectionController::SELECTION_IME_RAWINPUT:
return eIndexRawInput;
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
return eIndexSelRawText;
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
return eIndexConvText;
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
return eIndexSelConvText;
case nsISelectionController::SELECTION_SPELLCHECK:
return eIndexSpellChecker;
default:
NS_WARNING("non-IME selection type");
return eIndexRawInput;
}
}
protected:
nsTextFrame* mFrame;
nsPresContext* mPresContext;
@ -285,24 +312,25 @@ protected:
PRInt32 mSufficientContrast;
nscolor mFrameBackgroundColor;
// IME selection colors and underline info
struct nsIMEStyle {
// selection colors and underline info, the colors are resolved colors,
// i.e., the foreground color and background color are swapped if it's needed.
// And also line color will be resolved from them.
struct nsSelectionStyle {
PRBool mInit;
nscolor mTextColor;
nscolor mBGColor;
nscolor mUnderlineColor;
PRUint8 mUnderlineStyle;
float mUnderlineRelativeSize;
};
nsIMEStyle mIMEStyle[4];
// indices
float mIMEUnderlineRelativeSize;
nsSelectionStyle mSelectionStyle[5];
// Color initializations
void InitCommonColors();
PRBool InitSelectionColors();
nsIMEStyle* GetIMEStyle(PRInt32 aIndex);
void InitIMEStyle(PRInt32 aIndex);
nsSelectionStyle* GetSelectionStyle(PRInt32 aIndex);
void InitSelectionStyle(PRInt32 aIndex);
PRBool EnsureSufficientContrast(nscolor *aForeColor, nscolor *aBackColor);
@ -2947,9 +2975,8 @@ nsTextPaintStyle::nsTextPaintStyle(nsTextFrame* aFrame)
mInitCommonColors(PR_FALSE),
mInitSelectionColors(PR_FALSE)
{
for (int i = 0; i < 4; i++)
mIMEStyle[i].mInit = PR_FALSE;
mIMEUnderlineRelativeSize = -1.0f;
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mSelectionStyle); i++)
mSelectionStyle[i].mInit = PR_FALSE;
}
PRBool
@ -3027,32 +3054,32 @@ nsTextPaintStyle::GetIMESelectionColors(PRInt32 aIndex,
{
NS_ASSERTION(aForeColor, "aForeColor is null");
NS_ASSERTION(aBackColor, "aBackColor is null");
NS_ASSERTION(aIndex >= 0 && aIndex < 4, "Index out of range");
NS_ASSERTION(aIndex >= 0 && aIndex < 5, "Index out of range");
nsIMEStyle* IMEStyle = GetIMEStyle(aIndex);
*aForeColor = IMEStyle->mTextColor;
*aBackColor = IMEStyle->mBGColor;
nsSelectionStyle* selectionStyle = GetSelectionStyle(aIndex);
*aForeColor = selectionStyle->mTextColor;
*aBackColor = selectionStyle->mBGColor;
}
PRBool
nsTextPaintStyle::GetIMEUnderline(PRInt32 aIndex,
nscolor* aLineColor,
float* aRelativeSize,
PRUint8* aStyle)
nsTextPaintStyle::GetSelectionUnderlineForPaint(PRInt32 aIndex,
nscolor* aLineColor,
float* aRelativeSize,
PRUint8* aStyle)
{
NS_ASSERTION(aLineColor, "aLineColor is null");
NS_ASSERTION(aRelativeSize, "aRelativeSize is null");
NS_ASSERTION(aIndex >= 0 && aIndex < 4, "Index out of range");
NS_ASSERTION(aIndex >= 0 && aIndex < 5, "Index out of range");
nsIMEStyle* IMEStyle = GetIMEStyle(aIndex);
if (IMEStyle->mUnderlineStyle == NS_STYLE_BORDER_STYLE_NONE ||
IMEStyle->mUnderlineColor == NS_TRANSPARENT ||
mIMEUnderlineRelativeSize <= 0.0f)
nsSelectionStyle* selectionStyle = GetSelectionStyle(aIndex);
if (selectionStyle->mUnderlineStyle == NS_STYLE_BORDER_STYLE_NONE ||
selectionStyle->mUnderlineColor == NS_TRANSPARENT ||
selectionStyle->mUnderlineRelativeSize <= 0.0f)
return PR_FALSE;
*aLineColor = IMEStyle->mUnderlineColor;
*aRelativeSize = mIMEUnderlineRelativeSize;
*aStyle = IMEStyle->mUnderlineStyle;
*aLineColor = selectionStyle->mUnderlineColor;
*aRelativeSize = selectionStyle->mUnderlineRelativeSize;
*aStyle = selectionStyle->mUnderlineStyle;
return PR_TRUE;
}
@ -3180,60 +3207,77 @@ nsTextPaintStyle::InitSelectionColors()
return PR_TRUE;
}
nsTextPaintStyle::nsIMEStyle*
nsTextPaintStyle::GetIMEStyle(PRInt32 aIndex)
nsTextPaintStyle::nsSelectionStyle*
nsTextPaintStyle::GetSelectionStyle(PRInt32 aIndex)
{
InitIMEStyle(aIndex);
return &mIMEStyle[aIndex];
InitSelectionStyle(aIndex);
return &mSelectionStyle[aIndex];
}
struct StyleIDs {
nsILookAndFeel::nsColorID mForeground, mBackground, mLine;
nsILookAndFeel::nsMetricID mLineStyle;
nsILookAndFeel::nsMetricFloatID mLineRelativeSize;
};
static StyleIDs IMEStyleIDs[] = {
static StyleIDs SelectionStyleIDs[] = {
{ nsILookAndFeel::eColor_IMERawInputForeground,
nsILookAndFeel::eColor_IMERawInputBackground,
nsILookAndFeel::eColor_IMERawInputUnderline,
nsILookAndFeel::eMetric_IMERawInputUnderlineStyle },
nsILookAndFeel::eMetric_IMERawInputUnderlineStyle,
nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize },
{ nsILookAndFeel::eColor_IMESelectedRawTextForeground,
nsILookAndFeel::eColor_IMESelectedRawTextBackground,
nsILookAndFeel::eColor_IMESelectedRawTextUnderline,
nsILookAndFeel::eMetric_IMESelectedRawTextUnderlineStyle },
nsILookAndFeel::eMetric_IMESelectedRawTextUnderlineStyle,
nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize },
{ nsILookAndFeel::eColor_IMEConvertedTextForeground,
nsILookAndFeel::eColor_IMEConvertedTextBackground,
nsILookAndFeel::eColor_IMEConvertedTextUnderline,
nsILookAndFeel::eMetric_IMEConvertedTextUnderlineStyle },
nsILookAndFeel::eMetric_IMEConvertedTextUnderlineStyle,
nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize },
{ nsILookAndFeel::eColor_IMESelectedConvertedTextForeground,
nsILookAndFeel::eColor_IMESelectedConvertedTextBackground,
nsILookAndFeel::eColor_IMESelectedConvertedTextUnderline,
nsILookAndFeel::eMetric_IMESelectedConvertedTextUnderline }
nsILookAndFeel::eMetric_IMESelectedConvertedTextUnderline,
nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize },
{ nsILookAndFeel::eColor_LAST_COLOR,
nsILookAndFeel::eColor_LAST_COLOR,
nsILookAndFeel::eColor_SpellCheckerUnderline,
nsILookAndFeel::eMetric_SpellCheckerUnderlineStyle,
nsILookAndFeel::eMetricFloat_SpellCheckerUnderlineRelativeSize }
};
static PRUint8 sUnderlineStyles[] = {
NS_STYLE_BORDER_STYLE_NONE, // NS_UNDERLINE_STYLE_NONE 0
NS_STYLE_BORDER_STYLE_DOTTED, // NS_UNDERLINE_STYLE_DOTTED 1
NS_STYLE_BORDER_STYLE_DASHED, // NS_UNDERLINE_STYLE_DASHED 2
NS_STYLE_BORDER_STYLE_SOLID, // NS_UNDERLINE_STYLE_SOLID 3
NS_STYLE_BORDER_STYLE_DOUBLE // NS_UNDERLINE_STYLE_DOUBLE 4
nsCSSRendering::DECORATION_STYLE_NONE, // NS_UNDERLINE_STYLE_NONE 0
nsCSSRendering::DECORATION_STYLE_DOTTED, // NS_UNDERLINE_STYLE_DOTTED 1
nsCSSRendering::DECORATION_STYLE_DASHED, // NS_UNDERLINE_STYLE_DASHED 2
nsCSSRendering::DECORATION_STYLE_SOLID, // NS_UNDERLINE_STYLE_SOLID 3
nsCSSRendering::DECORATION_STYLE_DOUBLE, // NS_UNDERLINE_STYLE_DOUBLE 4
nsCSSRendering::DECORATION_STYLE_WAVY // NS_UNDERLINE_STYLE_WAVY 5
};
void
nsTextPaintStyle::InitIMEStyle(PRInt32 aIndex)
nsTextPaintStyle::InitSelectionStyle(PRInt32 aIndex)
{
nsIMEStyle* IMEStyle = &mIMEStyle[aIndex];
if (IMEStyle->mInit)
NS_ASSERTION(aIndex >= 0 && aIndex < 5, "aIndex is invalid");
nsSelectionStyle* selectionStyle = &mSelectionStyle[aIndex];
if (selectionStyle->mInit)
return;
StyleIDs* styleIDs = &IMEStyleIDs[aIndex];
StyleIDs* styleIDs = &SelectionStyleIDs[aIndex];
nsILookAndFeel* look = mPresContext->LookAndFeel();
nscolor foreColor, backColor, lineColor;
PRInt32 lineStyle;
look->GetColor(styleIDs->mForeground, foreColor);
look->GetColor(styleIDs->mBackground, backColor);
look->GetColor(styleIDs->mLine, lineColor);
look->GetMetric(styleIDs->mLineStyle, lineStyle);
nscolor foreColor, backColor;
if (styleIDs->mForeground == nsILookAndFeel::eColor_LAST_COLOR) {
foreColor = NS_SAME_AS_FOREGROUND_COLOR;
} else {
look->GetColor(styleIDs->mForeground, foreColor);
}
if (styleIDs->mBackground == nsILookAndFeel::eColor_LAST_COLOR) {
backColor = NS_TRANSPARENT;
} else {
look->GetColor(styleIDs->mBackground, backColor);
}
// Convert special color to actual color
NS_ASSERTION(foreColor != NS_TRANSPARENT,
@ -3248,23 +3292,59 @@ nsTextPaintStyle::InitIMEStyle(PRInt32 aIndex)
if (NS_GET_A(backColor) > 0)
EnsureSufficientContrast(&foreColor, &backColor);
nscolor lineColor;
float relativeSize;
PRUint8 lineStyle;
GetSelectionUnderline(mPresContext, aIndex,
&lineColor, &relativeSize, &lineStyle);
lineColor = GetResolvedForeColor(lineColor, foreColor, backColor);
if (!NS_IS_VALID_UNDERLINE_STYLE(lineStyle))
lineStyle = NS_UNDERLINE_STYLE_SOLID;
selectionStyle->mTextColor = foreColor;
selectionStyle->mBGColor = backColor;
selectionStyle->mUnderlineColor = lineColor;
selectionStyle->mUnderlineStyle = lineStyle;
selectionStyle->mUnderlineRelativeSize = relativeSize;
selectionStyle->mInit = PR_TRUE;
}
IMEStyle->mTextColor = foreColor;
IMEStyle->mBGColor = backColor;
IMEStyle->mUnderlineColor = lineColor;
IMEStyle->mUnderlineStyle = sUnderlineStyles[lineStyle];
IMEStyle->mInit = PR_TRUE;
/* static */ PRBool
nsTextPaintStyle::GetSelectionUnderline(nsPresContext* aPresContext,
PRInt32 aIndex,
nscolor* aLineColor,
float* aRelativeSize,
PRUint8* aStyle)
{
NS_ASSERTION(aPresContext, "aPresContext is null");
NS_ASSERTION(aRelativeSize, "aRelativeSize is null");
NS_ASSERTION(aStyle, "aStyle is null");
NS_ASSERTION(aIndex >= 0 && aIndex < 5, "Index out of range");
if (mIMEUnderlineRelativeSize == -1.0f) {
look->GetMetric(nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize,
mIMEUnderlineRelativeSize);
NS_ASSERTION(mIMEUnderlineRelativeSize >= 0.0f,
"underline size must be larger than 0");
nsILookAndFeel* look = aPresContext->LookAndFeel();
StyleIDs& styleID = SelectionStyleIDs[aIndex];
nscolor color;
float size;
PRInt32 style;
look->GetColor(styleID.mLine, color);
look->GetMetric(styleID.mLineStyle, style);
if (!NS_IS_VALID_UNDERLINE_STYLE(style)) {
NS_ERROR("Invalid underline style value is specified");
style = NS_UNDERLINE_STYLE_SOLID;
}
look->GetMetric(styleID.mLineRelativeSize, size);
NS_ASSERTION(size, "selection underline relative size must be larger than 0");
if (aLineColor) {
*aLineColor = color;
}
*aRelativeSize = size;
*aStyle = sUnderlineStyles[style];
return sUnderlineStyles[style] != nsCSSRendering::DECORATION_STYLE_NONE &&
color != NS_TRANSPARENT &&
size > 0.0f;
}
inline nscolor Get40PercentColor(nscolor aForeColor, nscolor aBackColor)
@ -3940,14 +4020,10 @@ nsTextFrame::UnionTextDecorationOverflow(nsPresContext* aPresContext,
// When this frame is not selected, the text-decoration area must be in
// frame bounds.
float ratio;
nsRect decorationRect;
if (!(GetStateBits() & NS_FRAME_SELECTED_CONTENT) ||
!HasSelectionOverflowingDecorations(aPresContext, &ratio))
!CombineSelectionUnderlineRect(aPresContext, *aOverflowRect))
return;
nsLineLayout::CombineTextDecorations(aPresContext,
NS_STYLE_TEXT_DECORATION_UNDERLINE,
this, *aOverflowRect, mAscent, ratio);
AddStateBits(TEXT_SELECTION_UNDERLINE_OVERFLOWED);
}
@ -3981,7 +4057,8 @@ nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
size.height = fontMetrics.underlineSize;
nsCSSRendering::PaintDecorationLine(
aCtx, lineColor, pt, size, ascent, fontMetrics.maxAscent,
NS_STYLE_TEXT_DECORATION_OVERLINE, NS_STYLE_BORDER_STYLE_SOLID);
NS_STYLE_TEXT_DECORATION_OVERLINE,
nsCSSRendering::DECORATION_STYLE_SOLID);
}
if (decorations.HasUnderline()) {
lineColor = aOverrideColor ? *aOverrideColor : decorations.mUnderColor;
@ -3989,7 +4066,8 @@ nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
gfxFloat offset = aProvider.GetFontGroup()->GetUnderlineOffset();
nsCSSRendering::PaintDecorationLine(
aCtx, lineColor, pt, size, ascent, offset,
NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_SOLID);
NS_STYLE_TEXT_DECORATION_UNDERLINE,
nsCSSRendering::DECORATION_STYLE_SOLID);
}
if (decorations.HasStrikeout()) {
lineColor = aOverrideColor ? *aOverrideColor : decorations.mStrikeColor;
@ -3997,7 +4075,8 @@ nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
gfxFloat offset = fontMetrics.strikeoutOffset;
nsCSSRendering::PaintDecorationLine(
aCtx, lineColor, pt, size, ascent, offset,
NS_STYLE_TEXT_DECORATION_LINE_THROUGH, NS_STYLE_BORDER_STYLE_SOLID);
NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
nsCSSRendering::DECORATION_STYLE_SOLID);
}
}
@ -4009,24 +4088,6 @@ static const SelectionType SelectionTypesWithDecorations =
nsISelectionController::SELECTION_IME_CONVERTEDTEXT |
nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT;
static void DrawIMEUnderline(gfxContext* aContext, PRInt32 aIndex,
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth,
gfxFloat aAscent, gfxFloat aSize, gfxFloat aOffset)
{
nscolor color;
float relativeSize;
PRUint8 style;
if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize, &style))
return;
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,
NS_STYLE_TEXT_DECORATION_UNDERLINE, style);
}
/**
* This, plus SelectionTypesWithDecorations, encapsulates all knowledge about
* drawing text decoration for selections.
@ -4035,38 +4096,45 @@ static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aPt, gfxFloat aWidth,
gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics)
{
gfxPoint pt(aPt);
gfxSize size(aWidth, aFontMetrics.underlineSize);
switch (aType) {
case nsISelectionController::SELECTION_IME_RAWINPUT:
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
// IME decoration lines should not be drawn on the both ends, i.e., we
// need to cut both edges of the decoration lines. Because same style
// IME selections can adjoin, but the users need to be able to know
// where are the boundaries of the selections.
//
// X: underline
//
// IME selection #1 IME selection #2 IME selection #3
// | | |
// | XXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXXX | XXXXXXXXXXXXXXXXXXX
// +---------------------+----------------------+--------------------
// ^ ^ ^ ^ ^
// gap gap gap
pt.x += 1.0;
size.width -= 2.0;
case nsISelectionController::SELECTION_SPELLCHECK: {
nsCSSRendering::PaintDecorationLine(
aContext, NS_RGB(255,0,0),
aPt, size, aAscent, aFontMetrics.underlineOffset,
NS_STYLE_TEXT_DECORATION_UNDERLINE, NS_STYLE_BORDER_STYLE_DOTTED);
float relativeSize;
PRUint8 style;
nscolor color;
PRInt32 index =
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aType);
if (aTextPaintStyle.GetSelectionUnderlineForPaint(index, &color,
&relativeSize,
&style)) {
size.height *= relativeSize;
nsCSSRendering::PaintDecorationLine(
aContext, color, pt, size, aAscent, aFontMetrics.underlineOffset,
NS_STYLE_TEXT_DECORATION_UNDERLINE, style);
}
break;
}
case nsISelectionController::SELECTION_IME_RAWINPUT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexRawInput,
aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset);
break;
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelRawText,
aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset);
break;
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexConvText,
aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset);
break;
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
DrawIMEUnderline(aContext, nsTextPaintStyle::eIndexSelConvText,
aTextPaintStyle, aPt, aWidth, aAscent, size.height,
aFontMetrics.underlineOffset);
break;
default:
NS_WARNING("Requested selection decorations when there aren't any");
break;
@ -4091,20 +4159,12 @@ static PRBool GetSelectionTextColors(SelectionType aType, nsTextPaintStyle& aTex
aTextPaintStyle.GetHighlightColors(aForeground, aBackground);
return PR_TRUE;
case nsISelectionController::SELECTION_IME_RAWINPUT:
aTextPaintStyle.GetIMESelectionColors(nsTextPaintStyle::eIndexRawInput,
aForeground, aBackground);
return PR_TRUE;
case nsISelectionController::SELECTION_IME_SELECTEDRAWTEXT:
aTextPaintStyle.GetIMESelectionColors(nsTextPaintStyle::eIndexSelRawText,
aForeground, aBackground);
return PR_TRUE;
case nsISelectionController::SELECTION_IME_CONVERTEDTEXT:
aTextPaintStyle.GetIMESelectionColors(nsTextPaintStyle::eIndexConvText,
aForeground, aBackground);
return PR_TRUE;
case nsISelectionController::SELECTION_IME_SELECTEDCONVERTEDTEXT:
aTextPaintStyle.GetIMESelectionColors(nsTextPaintStyle::eIndexSelConvText,
aForeground, aBackground);
aTextPaintStyle.GetIMESelectionColors(
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(aType),
aForeground, aBackground);
return PR_TRUE;
default:
@ -4707,29 +4767,53 @@ nsTextFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint) {
}
PRBool
nsTextFrame::HasSelectionOverflowingDecorations(nsPresContext* aPresContext,
float* aRatio)
nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext,
nsRect& aRect)
{
float ratio;
nsILookAndFeel* look = aPresContext->LookAndFeel();
look->GetMetric(nsILookAndFeel::eMetricFloat_IMEUnderlineRelativeSize, ratio);
if (aRatio)
*aRatio = ratio;
if (ratio <= 1.0f)
if (aRect.IsEmpty())
return PR_FALSE;
nsRect givenRect = aRect;
nsCOMPtr<nsIFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm.get());
gfxFontGroup* fontGroup = tfm->GetThebesFontGroup();
gfxFont* firstFont = fontGroup->GetFontAt(0);
if (!firstFont)
return PR_FALSE; // OOM
const gfxFont::Metrics& metrics = firstFont->GetMetrics();
gfxFloat underlineOffset = fontGroup->GetUnderlineOffset();
gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(mAscent);
SelectionDetails *details = GetSelectionDetails();
PRBool retval = PR_FALSE;
for (SelectionDetails *sd = details; sd; sd = sd->mNext) {
if (sd->mStart != sd->mEnd &&
sd->mType & SelectionTypesWithDecorations) {
retval = PR_TRUE;
break;
if (sd->mStart == sd->mEnd || !(sd->mType & SelectionTypesWithDecorations))
continue;
PRUint8 style;
float relativeSize;
PRInt32 index =
nsTextPaintStyle::GetUnderlineStyleIndexForSelectionType(sd->mType);
if (!nsTextPaintStyle::GetSelectionUnderline(aPresContext, index, nsnull,
&relativeSize, &style)) {
continue;
}
nsRect decorationArea;
gfxSize size(aPresContext->AppUnitsToGfxUnits(aRect.width),
metrics.underlineSize);
relativeSize = PR_MAX(relativeSize, 1.0f);
size.height *= relativeSize;
decorationArea =
nsCSSRendering::GetTextDecorationRect(aPresContext, size,
ascent, underlineOffset,
NS_STYLE_TEXT_DECORATION_UNDERLINE,
style);
aRect.UnionRect(aRect, decorationArea);
}
DestroySelectionDetails(details);
return retval;
return !aRect.IsEmpty() && !givenRect.Contains(aRect);
}
//null range means the whole thing
@ -4821,9 +4905,9 @@ nsTextFrame::SetSelected(nsPresContext* aPresContext,
// their underline is thicker than normal decoration line.
PRBool didHaveSelectionUnderline =
!!(mState & TEXT_SELECTION_UNDERLINE_OVERFLOWED);
PRBool willHaveSelectionUnderline =
aSelected && HasSelectionOverflowingDecorations(PresContext());
if (didHaveSelectionUnderline != willHaveSelectionUnderline) {
nsRect r(nsPoint(0, 0), GetSize());
if (didHaveSelectionUnderline != aSelected ||
(aSelected && CombineSelectionUnderlineRect(PresContext(), r))) {
PresContext()->PresShell()->FrameNeedsReflow(this,
nsIPresShell::eStyleChange,
NS_FRAME_IS_DIRTY);

View File

@ -70,6 +70,10 @@ _TEST_FILES = test_bug288789.html \
test_character_movement.html \
test_word_movement.html \
test_backspace_delete.xul \
test_selection_underline.html \
frame_selection_underline.xhtml \
frame_selection_underline-ref.xhtml \
frame_selection_underline.css \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" class="willBeRemoved">
<head>
<link rel="stylesheet" type="text/css" href="frame_selection_underline.css"/>
<script type="text/javascript" src="decorationline.js"></script>
</head>
<body class="reference">
<div id="selectionSpellChecker" class="selection"><div
class="fontsize size1"><div
class="font1"><span id="t0" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t1" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t2" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t3" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t4" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t5" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMERawInput" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t6" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t7" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t8" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t9" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t10">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t11">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMESelectedRawText" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t12">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t13">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t14">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t15">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t16">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t17">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMEConvertedText" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t18">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t19">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t20">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t21">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t22">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t23">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMESelectedConvertedText" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t24">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t25">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t26">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t27">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t28">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t29">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
</body>
</html>

View File

@ -0,0 +1,69 @@
html, body, div, span {
margin: 0;
padding: 0;
line-height: 1;
}
div.selection {
overflow: hidden;
display: block;
width: auto;
height: 100px;
white-space: nowrap;
}
div.fontsize {
display: inline-block;
width: auto;
height: auto;
}
div.fontsize.size1 {
font-size: 16px;
}
div.fontsize.size2 {
font-size: 32px;
}
div.fontsize.size3 {
font-size: 52px;
}
@font-face {
font-family: "AhemTest";
src: url(../../../fonts/Ahem.ttf);
}
@font-face {
font-family: "mplusTest";
src: url(../../../fonts/mplus/mplus-1p-regular.ttf);
}
div.font1,
div.font2 {
display: inline-block;
width: 120px;
height: 140px;
margin: 10px 1px;
overflow: hidden;
}
div.font1 {
font-family: "AhemTest";
}
div.font2 {
font-family: "mplusTest";
}
span {
text-align: top;
}
body.reference div.IMEselection span,
body.reference div.IMEselection span,
body.reference div.IMEselection span,
body.reference div.IMEselection span {
background-color: black;
}

View File

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" class="willBeRemoved">
<head>
<link rel="stylesheet" type="text/css" href="frame_selection_underline.css"/>
<script type="text/javascript" src="decorationline.js"></script>
<script type="text/javascript">
<![CDATA[
function onLoad()
{
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var docShell =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell);
var controller =
docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsISelectionDisplay)
.QueryInterface(Components.interfaces.nsISelectionController);
const selections = [
{
id: "selectionSpellChecker",
selectionType: controller.SELECTION_SPELLCHECK
},
{
id: "selectionIMERawInput",
selectionType: controller.SELECTION_IME_RAWINPUT
},
{
id: "selectionIMESelectedRawText",
selectionType: controller.SELECTION_IME_SELECTEDRAWTEXT
},
{
id: "selectionIMEConvertedText",
selectionType: controller.SELECTION_IME_CONVERTEDTEXT
},
{
id: "selectionIMESelectedConvertedText",
selectionType: controller.SELECTION_IME_SELECTEDCONVERTEDTEXT
},
];
for (var i = 0; i < selections.length; i++) {
var sel = controller.getSelection(selections[i].selectionType);
var range = document.createRange();
range.selectNodeContents(document.getElementById(selections[i].id));
sel.addRange(range);
}
document.documentElement.removeAttribute("class");
}
]]>
</script>
</head>
<body class="test" onload="onLoad();">
<div id="selectionSpellChecker" class="selection"><div
class="fontsize size1"><div
class="font1"><span id="t0" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t1" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t2" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t3" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t4" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t5" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMERawInput" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t6" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t7" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t8" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t9" >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t10">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t11">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMESelectedRawText" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t12">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t13">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t14">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t15">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t16">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t17">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMEConvertedText" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t18">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t19">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t20">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t21">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t22">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t23">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
<div id="selectionIMESelectedConvertedText" class="selection IMEselection"><div
class="fontsize size1"><div
class="font1"><span id="t24">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t25">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size2"><div
class="font1"><span id="t26">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t27">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div><div
class="fontsize size3"><div
class="font1"><span id="t28">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div><div
class="font2"><span id="t29">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div></div></div>
</body>
</html>

View File

@ -0,0 +1,412 @@
<html>
<head>
<title>Test for selection underline</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
<script type="text/javascript" src="../../base/tests/decoration_line_rendering.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript">
// Canvas related code stolen from layout/base/tests/bidi_numeral_test.js which
// stole from http://developer.mozilla.org/en/docs/Code_snippets:Canvas
const kStyleNames = [ "none", "dotted", "dashed", "solid", "double", "wavy" ];
var RemoteCanvas = function(aURL, aIsReference, aStyle, aRelativeSize) {
this.url = aURL;
this.id = kStyleNames[aStyle] + aRelativeSize;
if (aIsReference)
this.id = "ref-" + this.id;
this.isReference = aIsReference;
this.underlineStyle = aStyle;
this.underlineRelativeSize = aRelativeSize;
this.snapshot = null;
};
RemoteCanvas.CANVAS_WIDTH = 820;
RemoteCanvas.CANVAS_HEIGHT = 500;
RemoteCanvas.prototype.compare = function(otherCanvas, expected) {
var ret = compareSnapshots(this.snapshot, otherCanvas.snapshot, expected);
this.snapshotDataURL = ret[1];
otherCanvas.snapshotDataURL = ret[2];
return ret[0];
}
RemoteCanvas.prototype.load = function(callback) {
var iframe = document.createElement("iframe");
iframe.id = this.id;
iframe.width = RemoteCanvas.CANVAS_WIDTH + "px";
iframe.height = RemoteCanvas.CANVAS_HEIGHT + "px";
iframe.src = this.url;
var me = this;
iframe.addEventListener("load", function() {
me.remotePageLoaded(callback);
}, false);
window.document.body.appendChild(iframe);
};
const kIsMac = navigator.platform.indexOf("Mac") == 0;
const kIsWin = navigator.platform.indexOf("Win") == 0;
const kIsLinux = navigator.platform.indexOf("Linux") == 0;
/**
* gFontMetrics has predictable font metrics:
* 0: font-family: Ahem.ttf; font-size: 16px;
* 1: font-family: mplus-1p-regular.ttf; font-size: 16px;
* 2: font-family: Ahem.ttf; font-size: 32px;
* 3: font-family: mplus-1p-regular.ttf; font-size: 32px;
* 4: font-family: Ahem.ttf; font-size: 52px;
* 5: font-family: mplus-1p-regular.ttf; font-size: 52px;
*/
var gFontMetrics = [];
if (kIsWin) {
gFontMetrics = [
{ ascent: 13, offset: -2, lineHeight: 1 },
{ ascent: 17, offset: -2, lineHeight: 1 },
{ ascent: 26, offset: -4, lineHeight: 1 },
{ ascent: 34, offset: -4, lineHeight: 2 },
{ ascent: 42, offset: -7, lineHeight: 1 },
{ ascent: 56, offset: -7, lineHeight: 3 }
];
}
/*
if (kIsMac) {
// XXX mnakano: I got following metrics on my Mac (both 10.4 and 10.5).
// However, on tinderbox machines, they are different values. I'm not sure
// the reason.
gFontMetrics = [
{ ascent: 13, offset: -2.127930, lineHeight: 1.000000 },
{ ascent: 18, offset: -2.000000, lineHeight: 1.000000 },
{ ascent: 26, offset: -4.255859, lineHeight: 1.000000 },
{ ascent: 35, offset: -4.000000, lineHeight: 1.600098 },
{ ascent: 42, offset: -6.915771, lineHeight: 1.040222 },
{ ascent: 56, offset: -6.500000, lineHeight: 2.600159 }
];
}
if (kIsLinux) {
// XXX mnakano: I got following metrics on my Ubuntu 8.10. However, on
// tinderbox machines, they are different. Probably, the values depend on
// the version of FreeType and Pango. I bet we cannot test this on Linux
// without the way to get the actual font metrics from javascript.
gFontMetrics = [
{ ascent: 13, offset: -1.015625, lineHeight: 1.000000 },
{ ascent: 18, offset: -1.015625, lineHeight: 1.000000 },
{ ascent: 26, offset: -2.031250, lineHeight: 1.000000 },
{ ascent: 35, offset: -2.031250, lineHeight: 1.600003 },
{ ascent: 42, offset: -3.300781, lineHeight: 1.040001 },
{ ascent: 56, offset: -3.300781, lineHeight: 2.600002 }
];
}
*/
const kUnderlineStyles = [
{ color: "rgb(100%, 0%, 0%)", isIMESelection: false },
{ color: "rgb( 0%,100%, 0%)", isIMESelection: true },
{ color: "rgb( 0%, 0%,100%)", isIMESelection: true },
{ color: "rgb(100%,100%, 0%)", isIMESelection: true },
{ color: "rgb( 0%,100%,100%)", isIMESelection: true }
];
function drawSelectionDecorationLines(aDocument, aStyle, aRelativeSize)
{
var index = 0;
for (var i = 0; i < kUnderlineStyles.length; i++) {
var underlineStyle = kUnderlineStyles[i];
for (var j = 0; j < gFontMetrics.length; j++) {
var fontMetrics = gFontMetrics[j];
var element = aDocument.getElementById("t" + index++);
var pt = { x: element.getBoundingClientRect().left,
y: element.getBoundingClientRect().top };
var width = 120;
if (underlineStyle.isIMESelection) {
pt.x += 1;
width -= 1;
}
drawDecorationLine(aDocument, underlineStyle.color, pt,
{ width: width, height: fontMetrics.lineHeight * aRelativeSize },
fontMetrics.ascent, fontMetrics.offset, aStyle);
}
}
}
RemoteCanvas.prototype.remotePageLoaded = function(callback) {
var ldrFrame = document.getElementById(this.id);
if (this.isReference) {
var doc = ldrFrame.contentDocument;
drawSelectionDecorationLines(doc, this.underlineStyle,
this.underlineRelativeSize);
doc.documentElement.removeAttribute("class");
}
this.snapshot = snapshotWindow(ldrFrame.contentWindow);
callback(this);
};
var gPrefs = [
{
name: "ui.SpellCheckerUnderline",
type: "char",
newValue: "#ff0000"
},
{
name: "ui.IMERawInputBackground",
type: "char",
newValue: "#ffffff"
},
{
name: "ui.IMERawInputForeground",
type: "char",
newValue: "#000000"
},
{
name: "ui.IMERawInputUnderline",
type: "char",
newValue: "#00ff00"
},
{
name: "ui.IMESelectedRawTextBackground",
type: "char",
newValue: "#ffffff"
},
{
name: "ui.IMESelectedRawTextForeground",
type: "char",
newValue: "#000000"
},
{
name: "ui.IMESelectedRawTextUnderline",
type: "char",
newValue: "#0000ff"
},
{
name: "ui.IMEConvertedTextBackground",
type: "char",
newValue: "#ffffff"
},
{
name: "ui.IMEConvertedTextForeground",
type: "char",
newValue: "#000000"
},
{
name: "ui.IMEConvertedTextUnderline",
type: "char",
newValue: "#ffff00"
},
{
name: "ui.IMESelectedConvertedTextBackground",
type: "char",
newValue: "#ffffff"
},
{
name: "ui.IMESelectedConvertedTextForeground",
type: "char",
newValue: "#000000"
},
{
name: "ui.IMESelectedConvertedTextUnderline",
type: "char",
newValue: "#00ffff"
},
{
name: "ui.SpellCheckerUnderlineStyle",
type: "int",
newValue: 0
},
{
name: "ui.IMERawInputUnderlineStyle",
type: "int",
newValue: 0
},
{
name: "ui.IMESelectedRawTextUnderlineStyle",
type: "int",
newValue: 0
},
{
name: "ui.IMEConvertedTextUnderlineStyle",
type: "int",
newValue: 0
},
{
name: "ui.IMESelectedConvertedTextUnderlineStyle",
type: "int",
newValue: 0
},
{
name: "ui.SpellCheckerUnderlineRelativeSize",
type: "float",
newValue: 1.0
},
{
name: "ui.IMEUnderlineRelativeSize",
type: "float",
newValue: 1.0
}
];
function setPrefValue(aPrefs, aName, aType, aValue)
{
if (aType == "char")
aPrefs.setCharPref(aName, aValue);
else if (aType == "int")
aPrefs.setIntPref(aName, aValue);
else if (aType == "float")
aPrefs.setIntPref(aName, aValue * 100);
}
const kPrefStyles = [ 0, 3, 1, 2, 4, 5 ];
var gTests = [
{ size: 1.0, style: kDecorationStyleNone },
{ size: 1.0, style: kDecorationStyleSolid },
{ size: 1.0, style: kDecorationStyleDotted },
{ size: 1.0, style: kDecorationStyleDashed },
{ size: 1.0, style: kDecorationStyleDouble },
{ size: 1.0, style: kDecorationStyleWavy },
{ size: 2.0, style: kDecorationStyleNone },
{ size: 2.0, style: kDecorationStyleSolid },
{ size: 2.0, style: kDecorationStyleDotted },
{ size: 2.0, style: kDecorationStyleDashed },
{ size: 2.0, style: kDecorationStyleDouble },
{ size: 2.0, style: kDecorationStyleWavy }
];
function run()
{
var test = gTests.shift();
if (!test) {
SimpleTest.finish();
cleanup();
return;
}
netscape.security.PrivilegeManager.enablePrivilege(
'UniversalPreferencesRead UniversalPreferencesWrite UniversalXPConnect');
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
setPrefValue(prefs, "ui.SpellCheckerUnderlineRelativeSize", "float",
test.size);
setPrefValue(prefs, "ui.IMEUnderlineRelativeSize", "float",
test.size);
setPrefValue(prefs, "ui.SpellCheckerUnderlineStyle", "int",
kPrefStyles[test.style]);
setPrefValue(prefs, "ui.IMERawInputUnderlineStyle", "int",
kPrefStyles[test.style]);
setPrefValue(prefs, "ui.IMESelectedRawTextUnderlineStyle", "int",
kPrefStyles[test.style]);
setPrefValue(prefs, "ui.IMEConvertedTextUnderlineStyle", "int",
kPrefStyles[test.style]);
setPrefValue(prefs, "ui.IMESelectedConvertedTextUnderlineStyle", "int",
kPrefStyles[test.style]);
doTest(test.style, test.size);
}
function doTest(aStyle, aSize)
{
var canvases = [];
function callbackTestCanvas(canvas)
{
canvases.push(canvas);
if (canvases.length != 2)
return;
var result = !canvases[0].isReference ? canvases[0] : canvases[1];
var reference = canvases[0].isReference ? canvases[0] : canvases[1];
// when both canvases are loaded
ok(result.compare(reference, true),
"Rendering of reftest (style: " + kStyleNames[aStyle] +
", size: " + aSize + ") is different\n" +
"RESULT=" + result.snapshotDataURL + "\n" +
"REFERENCE=" + reference.snapshotDataURL + "\n");
var iframe = window.document.getElementById(canvases[0].id);
iframe.parentNode.removeChild(iframe);
iframe = window.document.getElementById(canvases[1].id);
iframe.parentNode.removeChild(iframe);
canvases = [];
setTimeout(run, 0);
}
var testCanvas = new RemoteCanvas("frame_selection_underline.xhtml",
false, aStyle, aSize);
testCanvas.load(callbackTestCanvas);
var refFile = "frame_selection_underline-ref.xhtml";
var refCanvas = new RemoteCanvas(refFile, true, aStyle, aSize);
refCanvas.load(callbackTestCanvas);
}
function onLoad()
{
SimpleTest.waitForExplicitFinish();
if (gFontMetrics.length == 0) {
todo(false, "test_selection_underline doesn't support this platform");
SimpleTest.finish();
return;
}
netscape.security.PrivilegeManager.enablePrivilege(
'UniversalPreferencesRead UniversalPreferencesWrite UniversalXPConnect');
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
for (var i = 0; i < gPrefs.length; i++) {
gPrefs[i].wasUserSetValue = prefs.prefHasUserValue(gPrefs[i].name);
if (gPrefs[i].wasUserSetValue) {
if (gPrefs[i].type == "char")
gPrefs[i].oldValue = prefs.getCharPref(gPrefs[i].name);
else if (gPrefs[i].type == "int")
gPrefs[i].oldValue = prefs.getIntPref(gPrefs[i].name);
else if (gPrefs[i].type == "float")
gPrefs[i].oldValue = prefs.getIntPref(gPrefs[i].name) / 100;
}
setPrefValue(prefs, gPrefs[i].name, gPrefs[i].type, gPrefs[i].newValue);
}
run();
}
function cleanup()
{
netscape.security.PrivilegeManager.enablePrivilege(
'UniversalPreferencesRead UniversalPreferencesWrite UniversalXPConnect');
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
for (var i = 0; i < gPrefs.length; i++) {
prefs.clearUserPref(gPrefs[i].name);
if (gPrefs[i].wasUserSetValue)
setPrefValue(prefs, gPrefs[i].name, gPrefs[i].type, gPrefs[i].oldValue);
}
}
</script>
</head>
<body onload="onLoad();">
<pre id="test">
</pre>
</body>
</html>

View File

@ -0,0 +1,50 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = Ahem.ttf \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/fonts

View File

@ -0,0 +1,50 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk
_TEST_FILES = mplus-1p-regular.ttf \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/fonts/mplus

View File

@ -471,17 +471,17 @@ nsTextBoxFrame::DrawText(nsIRenderingContext& aRenderingContext,
gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
if (decorations & NS_FONT_DECORATION_UNDERLINE) {
nsCSSRendering::PaintDecorationLine(ctx, underColor,
pt, gfxSize(width, sizePixel),
ascentPixel, offsetPixel,
NS_STYLE_TEXT_DECORATION_UNDERLINE,
NS_STYLE_BORDER_STYLE_SOLID);
pt, gfxSize(width, sizePixel),
ascentPixel, offsetPixel,
NS_STYLE_TEXT_DECORATION_UNDERLINE,
nsCSSRendering::DECORATION_STYLE_SOLID);
}
if (decorations & NS_FONT_DECORATION_OVERLINE) {
nsCSSRendering::PaintDecorationLine(ctx, overColor,
pt, gfxSize(width, sizePixel),
ascentPixel, ascentPixel,
NS_STYLE_TEXT_DECORATION_OVERLINE,
NS_STYLE_BORDER_STYLE_SOLID);
pt, gfxSize(width, sizePixel),
ascentPixel, ascentPixel,
NS_STYLE_TEXT_DECORATION_OVERLINE,
nsCSSRendering::DECORATION_STYLE_SOLID);
}
}
@ -555,10 +555,9 @@ nsTextBoxFrame::DrawText(nsIRenderingContext& aRenderingContext,
gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
nsCSSRendering::PaintDecorationLine(ctx, strikeColor,
pt, gfxSize(width, sizePixel),
ascentPixel, offsetPixel,
NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
NS_STYLE_BORDER_STYLE_SOLID);
pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel,
NS_STYLE_TEXT_DECORATION_LINE_THROUGH,
nsCSSRendering::DECORATION_STYLE_SOLID);
}
}

View File

@ -44,11 +44,10 @@
struct nsSize;
// {6672E0EA-C936-11DC-9BB7-0014850B592F}
// {EE288A5F-B98B-4105-B4AE-884F21588A92}
#define NS_ILOOKANDFEEL_IID \
{ 0x6672e0ea, 0xc936, 0x11dc, \
{ 0x9b, 0xb7, 0x00, 0x14, 0x85, 0x0b, 0x59, 0x2f} }
{ 0xee288a5f, 0xb98b, 0x4105, \
{ 0xb4, 0xae, 0x88, 0x4f, 0x21, 0x58, 0x8a, 0x92 } }
class nsILookAndFeel: public nsISupports {
public:
@ -91,6 +90,8 @@ public:
eColor_IMESelectedConvertedTextForeground,
eColor_IMESelectedConvertedTextUnderline,
eColor_SpellCheckerUnderline,
// New CSS 2 color definitions
eColor_activeborder,
eColor_activecaption,
@ -295,13 +296,14 @@ public:
eMetric_ScrollToClick,
/**
* IME underline styles, the values should be NS_DECORATION_LINE_STYLE_*.
* They are defined below.
* IME and spell checker underline styles, the values should be
* NS_DECORATION_LINE_STYLE_*. They are defined below.
*/
eMetric_IMERawInputUnderlineStyle,
eMetric_IMESelectedRawTextUnderlineStyle,
eMetric_IMEConvertedTextUnderlineStyle,
eMetric_IMESelectedConvertedTextUnderline,
eMetric_SpellCheckerUnderlineStyle,
/**
* If this metric != 0, show icons in menus.
@ -341,6 +343,7 @@ public:
eMetricFloat_ButtonVerticalInsidePadding,
eMetricFloat_ButtonHorizontalInsidePadding,
eMetricFloat_IMEUnderlineRelativeSize,
eMetricFloat_SpellCheckerUnderlineRelativeSize,
// The width/height ratio of the cursor. If used, the CaretWidth int metric
// should be added to the calculated caret width.
@ -394,9 +397,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsILookAndFeel, NS_ILOOKANDFEEL_IID)
// Of course if other plaforms work like the Mac, they can use it too.
#define NS_DONT_CHANGE_COLOR NS_RGB(0x01, 0x01, 0x01)
// --------------------------------
// Special colors for eColor_IME*
// --------------------------------
// -----------------------------------------------------------------
// Special colors for eColor_IME* and eColor_SpellCheckerUnderline
// -----------------------------------------------------------------
// For background color only.
#define NS_TRANSPARENT NS_RGBA(0x01, 0x00, 0x00, 0x00)
@ -404,9 +407,9 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsILookAndFeel, NS_ILOOKANDFEEL_IID)
#define NS_SAME_AS_FOREGROUND_COLOR NS_RGBA(0x02, 0x00, 0x00, 0x00)
#define NS_40PERCENT_FOREGROUND_COLOR NS_RGBA(0x03, 0x00, 0x00, 0x00)
#define NS_IS_IME_SPECIAL_COLOR(c) ((c) == NS_TRANSPARENT || \
(c) == NS_SAME_AS_FOREGROUND_COLOR || \
(c) == NS_40PERCENT_FOREGROUND_COLOR)
#define NS_IS_SELECTION_SPECIAL_COLOR(c) ((c) == NS_TRANSPARENT || \
(c) == NS_SAME_AS_FOREGROUND_COLOR || \
(c) == NS_40PERCENT_FOREGROUND_COLOR)
// -------------------------------------------------
// Underline styles for eMetric_IME*UnderlineStyle
@ -417,9 +420,10 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsILookAndFeel, NS_ILOOKANDFEEL_IID)
#define NS_UNDERLINE_STYLE_DASHED 2
#define NS_UNDERLINE_STYLE_SOLID 3
#define NS_UNDERLINE_STYLE_DOUBLE 4
#define NS_UNDERLINE_STYLE_WAVY 5
#define NS_IS_VALID_UNDERLINE_STYLE(s) \
(NS_UNDERLINE_STYLE_NONE <= (s) && (s) <= NS_UNDERLINE_STYLE_DOUBLE)
(NS_UNDERLINE_STYLE_NONE <= (s) && (s) <= NS_UNDERLINE_STYLE_WAVY)
// ------------------------------------------
// Bits for eMetric_AlertNotificationOrigin

View File

@ -129,6 +129,9 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
case eColor_IMESelectedRawTextUnderline:
case eColor_IMESelectedConvertedTextUnderline:
aColor = NS_TRANSPARENT;
break;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
break;
// two following colors get initialisation in XPLookAndFeel.
//eColor_TextSelectBackgroundDisabled,
@ -441,6 +444,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_IMESelectedConvertedTextUnderline:
aMetric = NS_UNDERLINE_STYLE_NONE;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_WAVY;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
@ -483,6 +489,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetri
case eMetricFloat_IMEUnderlineRelativeSize:
aMetric = 1.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 1.0f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;

View File

@ -155,7 +155,10 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
case eColor_IMESelectedConvertedTextUnderline:
aColor = NS_SAME_AS_FOREGROUND_COLOR;
break;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
break;
//
// css2 system colors http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
//
@ -670,6 +673,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_IMESelectedConvertedTextUnderline:
aMetric = NS_UNDERLINE_STYLE_SOLID;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_DOTTED;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
@ -714,6 +720,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetri
case eMetricFloat_IMEUnderlineRelativeSize:
aMetric = 2.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 2.0f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;

View File

@ -153,6 +153,9 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor& aColor)
case eColor_IMESelectedConvertedTextUnderline:
aColor = NS_TRANSPARENT;
break;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
break;
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
case eColor_activeborder:
@ -578,6 +581,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_IMESelectedConvertedTextUnderline:
aMetric = NS_UNDERLINE_STYLE_NONE;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_WAVY;
break;
case eMetric_ImagesInMenus:
aMetric = moz_gtk_images_in_menus();
break;
@ -626,6 +632,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID,
case eMetricFloat_IMEUnderlineRelativeSize:
aMetric = 1.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 1.0f;
break;
case eMetricFloat_CaretAspectRatio:
aMetric = sCaretRatio;
break;

View File

@ -114,6 +114,9 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
case eColor_IMESelectedConvertedTextUnderline:
aColor = NS_TRANSPARENT;
return NS_OK;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
return NS_OK;
// New CSS 2 Color definitions
case eColor_activeborder:
@ -389,6 +392,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_IMESelectedConvertedTextUnderline:
aMetric = NS_UNDERLINE_STYLE_NONE;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_WAVY;
break;
default:
aMetric = 0;
@ -432,6 +438,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetri
case eMetricFloat_IMEUnderlineRelativeSize:
aMetric = 1.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 1.0f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;

View File

@ -118,6 +118,9 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
case eColor_IMESelectedRawTextUnderline:
case eColor_IMESelectedConvertedTextUnderline:
aColor = NS_TRANSPARENT;
break;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
break;
// css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
@ -381,6 +384,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_IMESelectedConvertedTextUnderline:
aMetric = NS_UNDERLINE_STYLE_NONE;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_WAVY;
break;
default:
aMetric = 0;
@ -427,6 +433,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetri
case eMetricFloat_IMEUnderlineRelativeSize:
aMetric = 1.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 1.0f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;

View File

@ -142,6 +142,10 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID,nscolor &aColor)
aColor = NS_TRANSPARENT;
break;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
break;
case eColor_activeborder:
aColor = QCOLOR_TO_NS_RGB(palette.color(QPalette::Normal, QPalette::Window));
break;
@ -481,6 +485,10 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID,PRInt32 &aMetric)
res = NS_ERROR_NOT_IMPLEMENTED;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_WAVY;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
@ -551,6 +559,10 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID,
aMetric = 1.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 1.0f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;

View File

@ -162,6 +162,9 @@ nsresult nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
case eColor_IMESelectedConvertedTextUnderline:
aColor = NS_TRANSPARENT;
return NS_OK;
case eColor_SpellCheckerUnderline:
aColor = NS_RGB(0xff, 0, 0);
return NS_OK;
// New CSS 2 Color definitions
case eColor_activeborder:
@ -599,6 +602,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricID aID, PRInt32 & aMetric)
case eMetric_IMESelectedConvertedTextUnderline:
aMetric = NS_UNDERLINE_STYLE_NONE;
break;
case eMetric_SpellCheckerUnderlineStyle:
aMetric = NS_UNDERLINE_STYLE_WAVY;
break;
default:
aMetric = 0;
res = NS_ERROR_FAILURE;
@ -641,6 +647,9 @@ NS_IMETHODIMP nsLookAndFeel::GetMetric(const nsMetricFloatID aID, float & aMetri
case eMetricFloat_IMEUnderlineRelativeSize:
aMetric = 1.0f;
break;
case eMetricFloat_SpellCheckerUnderlineRelativeSize:
aMetric = 1.0f;
break;
default:
aMetric = -1.0;
res = NS_ERROR_FAILURE;

View File

@ -121,6 +121,8 @@ nsLookAndFeelIntPref nsXPLookAndFeel::sIntPrefs[] =
eMetric_IMEConvertedTextUnderlineStyle, PR_FALSE, nsLookAndFeelTypeInt, 0 },
{ "ui.IMESelectedConvertedTextUnderlineStyle",
eMetric_IMESelectedConvertedTextUnderline, PR_FALSE, nsLookAndFeelTypeInt, 0 },
{ "ui.SpellCheckerUnderlineStyle",
eMetric_SpellCheckerUnderlineStyle, PR_FALSE, nsLookAndFeelTypeInt, 0 },
};
nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] =
@ -143,6 +145,9 @@ nsLookAndFeelFloatPref nsXPLookAndFeel::sFloatPrefs[] =
PR_FALSE, nsLookAndFeelTypeFloat, 0 },
{ "ui.IMEUnderlineRelativeSize", eMetricFloat_IMEUnderlineRelativeSize,
PR_FALSE, nsLookAndFeelTypeFloat, 0 },
{ "ui.SpellCheckerUnderlineRelativeSize",
eMetricFloat_SpellCheckerUnderlineRelativeSize, PR_FALSE,
nsLookAndFeelTypeFloat, 0 },
{ "ui.caretAspectRatio", eMetricFloat_CaretAspectRatio, PR_FALSE,
nsLookAndFeelTypeFloat, 0 },
};
@ -184,6 +189,7 @@ const char nsXPLookAndFeel::sColorPrefs[][38] =
"ui.IMESelectedConvertedTextBackground",
"ui.IMESelectedConvertedTextForeground",
"ui.IMESelectedConvertedTextUnderline",
"ui.SpellCheckerUnderline",
"ui.activeborder",
"ui.activecaption",
"ui.appworkspace",
@ -485,7 +491,8 @@ nsXPLookAndFeel::IsSpecialColor(const nsColorID aID, nscolor &aColor)
case eColor_IMEConvertedTextUnderline:
case eColor_IMESelectedRawTextUnderline:
case eColor_IMESelectedConvertedTextUnderline:
return NS_IS_IME_SPECIAL_COLOR(aColor);
case eColor_SpellCheckerUnderline:
return NS_IS_SELECTION_SPECIAL_COLOR(aColor);
default:
/*
* In GetColor(), every color that is not a special color is color